Kazakhstan E-Invoice
How to get “API Key” from Portal ?
To obtain the API key to be used in the request body of the login endpoint, navigate to Settings > ERP Management > API Management in the Portal and use the "Generate" button.
Login and Authorization Configuration
Technical Details
| Property | Value |
|---|---|
| Endpoint | /auth/login |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | None (Initial access) |
Request Body (JSON)
The following fields are used to define login criteria:
| Field | Type | Description |
|---|---|---|
| apiKey | String | A unique key assigned specifically to the user for portal access, verifying the system identity. (it is explained in previous section “How to get API Key from portal”) |
| String | The registered email address in the system belonging to the authorized user performing the operation. |
Response Details
Upon a successful request, a 200 OK code is returned with the following details:
| Field | Type | Description |
|---|---|---|
| jwt | — | The secure session token that must be used as a 'R-Auth' API Key in all subsequent API calls. |
| expirationDate | DateTime | Indicates the exact time the session key will expire; the ERP system can use this data to manage automatic re-login processes. |
The JWT token successfully obtained during the authentication step (auth/login) acts as a key to access the secure endpoints of the APIs. After the first successful login, the JWT token obtained from the response of a successful login is used as the R-Auth value in the authorization section of other queries. This configuration ensures that every data exchange between the ERP and the portal occurs over an authenticated and secure channel.
Using the R-Auth Header in Requests
| Property | Value |
|---|---|
| Key | Enter R-Auth in the Key field. |
| Value | {{apiKey}} or {{jwt}} (Copy the jwt string returned from the login endpoint.) |
| Header Setting | Navigate to the "Headers" tab of the request to be sent. |
1. Introduction
This guide is structured to allow development teams to incorporate portal features into their business workflows with minimum effort and maximum compliance.
⚠️ Availability (October 2026): The following are available on the stage environment and are not yet on production: SNT, AVR and VWH documents on send-document-async (Section 4), the AVR endpoints under /api/sap/awp and /api/awp (AVR section), the KGD registration number of an AVR, and the status credit described below. The AVR PDF (AVR section, 4. Download AVR PDF) is not yet on stage either. Production availability will be announced separately.
Status credit (KGD status updates)
Every new status that KGD reports for a Kazakhstan document costs one credit, taken from the same plan as the document credit and charged on top of it. This applies to ESF, SNT, AVR and virtual warehouse (VWH UForm and ZVT) documents, in both directions.
- The same status is charged once per document: a document that goes CREATED → DELIVERED → CREATED pays for CREATED once.
- The first status read after an upload is charged too.
- Statuses are charged whether Docnova reads them on its own schedule or one of the status endpoints below asks KGD.
- Companies that are exempt are not charged; their statuses are still recorded.
When the company has no credit left:
- Docnova stops asking KGD about that company's documents and resumes on its own once credit is added. Pending documents are not marked as failed.
- The endpoints that ask KGD for a status answer HTTP 400 with errorType LIFECYCLE_CREDIT_EXHAUSTED without calling KGD: /esf/get-invoice-status-list-by-id, /esf/unread-invoices (only when there are unread invoices to ask about), /snt/query-snt-status-by-id, /snt/query-status-by-regnum, /esf/awp/query-status-by-id, /kz/vwh/internal/uform/{id}/status, /kz/vwh/internal/uform/details/{id} and /kz/vwh/internal/zvt/regnum. Send the same request again after credit is added.
- Status responses gain two fields: statusSyncPaused (true) and statusSyncPausedReason. Both are omitted when updates are not paused; no existing field changes. They appear in additionalData of Section 8 (Document Status), at the top level of Section 9 and Section 10, and at the top level of the AVR responses (/api/sap/awp/create, GET /api/awp/{id}).
{
"statusSyncPaused": true,
"statusSyncPausedReason": "Kazakhstan document status updates are paused: the company has no credits left. Add credits to resume."
}
2. Authentication POST
Purpose of Use: This endpoint is utilized by ERP systems to obtain the session key (JWT Token) required to establish a secure connection and initiate data exchange with the docnova portal.
An enterprise ERP system must trigger this endpoint to receive a valid authentication token before performing actions such as transmitting invoices or querying compliance reports via the portal. The acquired token is then provided in the "Authorization" header for all subsequent API requests. This mechanism ensures that data traffic between the ERP and the portal is conducted via a secure, time-bound key rather than transmitting sensitive user credentials for every transaction.
Endpoint Information
| Property | Value |
|---|---|
| URL | /auth/login |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | Not required (public endpoint) |
Example Request
curl --location 'https://api-stage.docnova.ai/auth/login' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--data-raw '{
"apiKey": "{{your_api_key}}",
"email": "user@example.com"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| String | Optional | User's registered email address | |
| apiKey | String | Yes | Obtained from the portal, via the settings > ERP Management > API Management menu. |
Responses
200 - Login Successful
Full Response (AccountInfo)
{
"id": "a1b2c3d4-e5f6-7890-abcd-...",
"superAdmin": false,
"companies": [
{
"id": "60ccd1a7-5348-47b2-9ef6-...",
"name": "Example Company LLP",
"taxNumber": "123456789012",
"vatNumber": "123456789012",
"email": "info@example.com",
"website": "https://www.example.com",
"address": "Kabanbay Batyr Ave 15",
"city": "Astana",
"state": "Astana",
"country": "KZ",
"postalCode": "010000",
"phoneNumber": "+7 7172 123456",
"credit": 1000,
"userCount": 5,
"portalType": "KZ",
"mailLanguage": "RU",
"currencyCode": "KZT",
"sftp": false,
"isSubCompany": false,
"featureAllowed": true,
"participants": []
}
],
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expirationDate": "2026-01-30T10:30:00.000Z",
"refreshToken": "refresh-token-string",
"refreshTokenExpiration": "2026-02-28T10:30:00.000Z",
"user": {
"id": "user-uuid",
"email": "user@example.com",
"firstName": "Aidar",
"lastName": "Nurlanov",
"phoneNumber": "+7 701 1234567",
"photoUrl": "https://example.com/photo.jpg",
"mailLang": "RU",
"isSuperAdmin": false,
"lastLoginTime": "2026-01-29T10:30:00",
"featureAllowed": true
},
"mfaEnabled": false,
"mfaType": null,
"secretImageUri": null,
"lastCompanyId": "60ccd1a7-5348-47b2-9ef6-...",
"requiresRecaptchaV2": false,
"message": null,
"active": true,
"isAppLogin": false
}
Basic Response (JwtBasicResponse)
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expirationDate": "2026-01-30T10:30:00.000Z"
}
Response Fields
Account Information Fields
| Field | Type | Description |
|---|---|---|
| id | String | User unique identifier |
| superAdmin | Boolean | Whether user has super admin privileges |
| companies | Array<AuthorizedCompany> | List of companies user is authorized to access |
| jwt | String | JWT access token. Used in R-Auth header for API requests |
| expirationDate | DateTime | JWT token expiration date |
| refreshToken | String | Refresh token for obtaining new access tokens |
| refreshTokenExpiration | DateTime | Refresh token expiration date |
| user | Object | User detail information |
| mfaEnabled | Boolean | Whether multi factor authentication is enabled |
| mfaType | Enum | MFA type (GOOGLE, WHATSAPP) |
| secretImageUri | String | Google Authenticator QR code URI |
| lastCompanyId | String | Last selected company ID |
| requiresRecaptchaV2 | Boolean | Whether reCAPTCHA v2 verification is required |
| message | String | Status message (e.g., "MFA required") |
| active | Boolean | Whether user account is active |
| isAppLogin | Boolean | Whether this is a mobile app login |
Parameter Values Reference Table
currentCountry Values (Relevant to Kazakhstan)
| Value | Description |
|---|---|
| KZ | Kazakhstan |
| GLOBAL | Global (default, used before a company has selected a country) |
Shared enum: currentCountry is a platform-wide field shared by every country the portal operates in; only KZ is relevant to a Kazakhstan company.
Company Information Fields
| Field | Type | Description |
|---|---|---|
| id | String | Company unique identifier |
| name | String | Company name |
| taxNumber | String | Tax number |
| vatNumber | String | VAT number |
| String | Company email address | |
| website | String | Company website |
| address | String | Address |
| city | String | City |
| state | String | State or Region |
| country | Enum | Country code |
| postalCode | String | Postal code |
| phoneNumber | String | Phone number |
| faxNumber | String | Fax number |
| credit | Integer | Available credit |
| userCount | Integer | Total user count |
| portalType | Enum | Portal type |
| mailLanguage | Enum | Email language |
| currencyCode | String | Currency code |
| sftp | Boolean | Whether SFTP integration is active |
| isSubCompany | Boolean | Whether it's a sub company |
| featureAllowed | Boolean | Whether feature access is granted |
| participants | Array | Peppol participant information |
User Information Fields
| Field | Type | Description |
|---|---|---|
| id | String | User unique identifier |
| String | User email address | |
| firstName | String | User first name |
| lastName | String | User last name |
| phoneNumber | String | User phone number |
| photoUrl | String | User photo URL |
| mailLang | Enum | User email language |
| isSuperAdmin | Boolean | Whether user has super admin privileges |
| lastLoginTime | DateTime | Last login time |
| featureAllowed | Boolean | Whether feature access is granted |
Enum Values Reference Table
mfaType Values
| Value | Description |
|---|---|
| Google Authenticator verification | |
| WhatsApp verification |
portalType Values (Relevant to Kazakhstan)
| Value | Description |
|---|---|
| KZ | Kazakhstan portal |
| DEFAULT | Default portal (used when no country-specific portal applies) |
mailLanguage Values (Relevant to Kazakhstan)
| Value | Description |
|---|---|
| KK | Kazakh |
| RU | Russian |
| EN | English |
Shared enum: mailLanguage also accepts the platform's other supported languages (DE, ES, FR, IT, MS, NL, PL, RO, TR), but a Kazakhstan company only needs KK, RU or EN — these are also the three languages the ESF PDF stylesheet (Section 7) can render.
200 - Login Successful
Basic Response (JwtBasicResponse)
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expirationDate": "2026-01-30T10:30:00.000Z"
}
401 - Unauthorized
{
"timestamp": "2026-01-29T10:30:00.000Z",
"status": 401,
"error": "Unauthorized",
"message": "Invalid email or password"
}
403 - MFA Required
{
"id": "user-uuid",
"mfaEnabled": true,
"mfaType": "GOOGLE",
"message": "MFA verification required",
"jwt": null
}
429 - Too Many Requests
{
"timestamp": "2026-01-29T10:30:00.000Z",
"status": 429,
"error": "Too Many Requests",
"message": "Too many failed login attempts. Please try again later.",
"requiresRecaptchaV2": true
}
3. Send Document (Synchronous) POST
Purpose of Use: The POST /invoice/send-document endpoint is the legacy synchronous ERP submission path. For Kazakhstan it accepts a Base64-encoded ESF V2 XML document, recognizes it, creates the shared invoice record, submits it to the ESF service and returns the result — all within a single HTTP call. This is currently the only country that calls this legacy endpoint; every other integration uses the asynchronous equivalents below.
⚠️ Note: Because the ESF submission (signing + SOAP upload) happens inline, this call can take longer than send-document-async. For high-volume ERPs, prefer the asynchronous endpoint and poll /invoice/document-status/{trackingId} instead.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/send-document |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/send-document' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"compId": "79499e36-6d45-4c7d-bc52-...",
"base64Document": "<BASE64_ENCODED_ESF_V2_XML>",
"receiverEmails": ["buyer@example.kz"],
"mailTemplateId": null,
"validationVersion": null
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| compId | String (UUID) | Yes | The company the document is filed against. The authenticated user must belong to this company. |
| base64Document | String (Base64) | Yes* | Base64-encoded ESF V2 XML. Required unless base64Pdf is supplied instead (ZUGFeRD-style PDF intake; not used for KZ ESF). |
| base64Pdf | String (Base64) | No | Not applicable to Kazakhstan ESF submissions — present for ZUGFeRD-family countries only. |
| receiverEmails | Array<String> | No | Recipient email addresses for the generated invoice notification. |
| mailTemplateId | String | No | Custom email template identifier. |
| validationVersion | String | No | Not used for Kazakhstan; relevant to France only. |
Responses
200 - Processing Result
⚠️ Note: This endpoint always answers with HTTP 200, even on failure — check the message/errors fields to determine the real outcome.
{
"uuid": "b34afc0b-4f5d-4670-910c-...",
"trackingId": "dd240417-5896-4577-ae51-...",
"message": null,
"peppolSendingResult": null,
"invoiceNumber": "00900023888",
"errors": [],
"target": null,
"additionalData": {
"kgdInvoiceId": 22116203282,
"esfStatus": "KZ_CREATED"
},
"processing": null
}
Response Field Descriptions
| Field | Type | Description |
|---|---|---|
| uuid | UUID | null | Shared invoice identifier. Null when the document could not be saved. |
| trackingId | UUID | Identifier of the document-processing record created for this call. |
| message | String | null | "ERROR" when the submission failed; null on success. |
| peppolSendingResult | String (Enum) | null | Not populated for Kazakhstan (Peppol-only field). |
| invoiceNumber | String | null | Invoice number extracted from the ESF XML. |
| errors | Array<String> | List of error messages. Empty on success. |
| target | String (Enum) | null | Not populated for Kazakhstan. |
| additionalData | Object | null | KZ-specific metadata: kgdInvoiceId (the provider's numeric invoice id) and esfStatus (see the ESF status table in Section 10 — Get Document Status by Document ID). |
| processing | Boolean | null | true when the ESF result could not be confirmed yet and is being reconciled with the provider; the official outcome is neither accepted nor rejected. Null for every other outcome. |
403 - Forbidden
Returned when the authenticated user does not belong to the company identified by compId.
401 - Unauthorized
Returned when the R-Auth header is missing, invalid, or expired.
4. Send Document Async POST
Purpose of Use: This endpoint lets an ERP system hand a Kazakhstan document to Docnova for submission to KGD (IS ESF) without waiting for KGD. It accepts every Kazakhstan document type: the ESF invoice (invoiceType), the SNT waybill and the AVR (waybillType), and the six virtual warehouse U-Forms (warehouseDocumentType).
The ERP sends the KGD XML document itself, Base64-encoded (or uploads it first and sends its documentKey). Signing is performed server-side with the company's registered KGD certificate, so the ERP does not handle certificates. The call returns at once with a trackingId and status PENDING; Docnova then signs the document, uploads it to KGD and records the result. Read the result with Section 8 (Document Status) — see "Results by document type" there.
A trackingId reaches KGD at most once: if the queue delivers the same message again, the document is not uploaded a second time. To send again, make a new request.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/send-document-async |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | JWT Token (R-Auth header) or API Key |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {{jwt_token}}' \
--data-raw '{
"apiKey": "{{user_api_key}}",
"base64Document": "{{base64_encoded_xml}}",
"businessType": "B2B",
"compId": "{{company_uuid}}",
"invoiceType": "KZ_ESF_V2"
}'
SNT (waybill):
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async' \
--header 'Content-Type: application/json' \
--header 'R-Auth: {{jwt_token}}' \
--data-raw '{
"compId": "{{company_uuid}}",
"waybillType": "KZ_SNT",
"base64Document": "{{base64_encoded_snt_xml}}"
}'
AVR (act of completed works):
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async' \
--header 'Content-Type: application/json' \
--header 'R-Auth: {{jwt_token}}' \
--data-raw '{
"compId": "{{company_uuid}}",
"waybillType": "KZ_AWP",
"base64Document": "{{base64_encoded_awp_v1_xml}}",
"senderSignerName": "Генеральный директор"
}'
Virtual warehouse U-Form:
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async' \
--header 'Content-Type: application/json' \
--header 'R-Auth: {{jwt_token}}' \
--data-raw '{
"compId": "{{company_uuid}}",
"warehouseDocumentType": "MOVEMENT",
"base64Document": "{{base64_encoded_uform_xml}}"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| compId | String (UUID) | Conditional* | Company unique identifier. Required if apiKey is not provided. |
| apiKey | String | Conditional* | API key. Required if compId is not provided. |
| base64Document | String | Conditional** | The KGD XML document (ESF, SNT, AVR or U-Form), UTF-8, Base64-encoded. A PDF is refused: only the XML can be signed and filed with KGD. |
| documentKey | String | Conditional** | The key returned by Section 6 (Presigned Upload) after the XML was uploaded there. The same key cannot be submitted again within 10 minutes (HTTP 429). |
| invoiceType | Enum | Conditional*** | KZ_ESF_V2 for an ESF invoice. |
| waybillType | Enum | Conditional*** | KZ_SNT for an SNT, KZ_AWP for an AVR. |
| warehouseDocumentType | Enum | Conditional*** | The virtual warehouse U-Form type (see the table below). |
| senderSignerName | String | AVR only | The position of the person who signs the AVR on the sender side (e.g. Генеральный директор). Required when waybillType is KZ_AWP; ignored otherwise. |
| businessType | Enum | No | Business model type (B2B, B2C, B2G). |
Note:
- (*) At least one of compId or apiKey must be provided.
- (**) One of base64Document or documentKey must be provided.
- (***) Exactly one of invoiceType, waybillType or warehouseDocumentType must be provided. A request that declares two of them is refused with HTTP 400.
- One SNT, one AVR or one U-Form per request.
- An AVR goes through the same checks, duplicate-number check, credit, signing and KGD upload as POST /api/sap/awp/create (AVR section); its XML rules are described there.
businessType Values
| Value | Description |
|---|---|
| B2B | Business to Business |
| B2C | Business to Consumer |
| B2G | Business to Government |
invoiceType Values (Relevant to Kazakhstan)
| Value | Group | Description |
|---|---|---|
| KZ_ESF_V2 | Kazakhstan | Kazakhstan ESF v2 — the only value a Kazakhstan company should send. |
Shared enum: invoiceType also accepts every other country's format codes (XRechnung, ZUGFeRD, Factur-X, KSeF, etc.) since this endpoint is shared across the whole platform — they are not applicable to a Kazakhstan company and are omitted here.
waybillType Values (Relevant to Kazakhstan)
| Value | Description |
|---|---|
| KZ_SNT | SNT (сопроводительная накладная на товары) — one SNT XML per request. Signed with the company's newest KGD certificate. |
| KZ_AWP | AVR (акт выполненных работ), AwpV1 XML. senderSignerName is required. |
warehouseDocumentType Values
| Value | Description |
|---|---|
| BALANCE | Opening balance U-Form |
| MANUFACTURE | Manufacture U-Form |
| MOVEMENT | Movement U-Form |
| WRITE_OFF | Write-off U-Form |
| BALANCE_CORRECTION | Balance correction U-Form |
| DETAILING | Detailing U-Form |
Responses
200 - Successful Response
{
"trackingId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "PENDING",
"message": "Document queued for processing"
}
Response Fields
| Field | Type | Description |
|---|---|---|
| trackingId | UUID | Unique process tracking identifier. This ID can be used to query the processing status. |
| status | Enum | Current status of the process. |
| message | String | Descriptive message about the status. |
status Values
| Value | Description |
|---|---|
| PENDING | Process queued, not yet started |
| PROCESSING | Process in progress |
| COMPLETED | Process completed successfully |
| FAILED | Process failed |
| SENDING_FAILED | Sending failed |
| PERMANENT_FAILED | Permanent failure, will not be retried |
400 - Bad Request
{
"trackingId": null,
"status": "FAILED",
"message": "Either invoiceType or waybillType must be provided"
}
An AVR (waybillType = KZ_AWP) without senderSignerName is refused before anything is queued; no tracking record is created:
{
"errorType": "MISSING_SENDER_SIGNER_NAME",
"errorMessage": "senderSignerName (position of the signer) is required"
}
401 - Unauthorized
{
"timestamp": "2026-01-29T10:30:00.000Z",
"status": 401,
"error": "Unauthorized",
"message": "Invalid or expired token"
}
500 - Internal Server Error
{
"trackingId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "FAILED",
"message": "An unexpected error occurred"
}
5. Send Document Async (JSON) POST
Purpose of Use: The POST /invoice/send-document-async-json endpoint accepts invoice data as a structured JSON object (ublDto) instead of a pre-built XML file — this is the platform's shared cross-country JSON invoice model. For Kazakhstan, the platform converts that JSON into ESF V2 XML — applying the KZ invoice type code and KZ-specific extensions — and submits it through the same KazakhstanInvoiceService used by every other creation channel.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/send-document-async-json |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async-json' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"ublDto": {
"companyId": "79499e36-6d45-4c7d-bc52-...",
"invoiceType": "KZ_ESF_V2"
},
"apiKey": null,
"receiverEmails": ["buyer@example.kz"],
"senderEmail": null,
"mailTemplateId": null,
"businessType": "B2B",
"validationVersion": null,
"method": null
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| ublDto | Object | Yes | The invoice payload as a structured JSON object. companyId inside it is required unless apiKey is supplied at the top level. |
| apiKey | String | No* | Resolves the company when ublDto.companyId is omitted. One of the two is required. |
| receiverEmails | Array<String> | No | Recipient email addresses for the generated invoice notification. |
| senderEmail | String | No | Overrides the sender address used on the notification email. |
| mailTemplateId | String | No | Custom email template identifier. |
| businessType | String (Enum) | No | B2B, B2C, or B2G. Declared out-of-band; not carried by the XML element set. |
| validationVersion | String | No | Not used for Kazakhstan; relevant to France only. |
| method | String (Enum) | No | Send-channel selection for Peppol/XRechnung/ZUGFeRD countries (via peppol, via email). Not applicable to Kazakhstan ESF delivery. |
Responses
200 - Document Accepted for Processing
{
"trackingId": "dd240417-5896-4577-ae51-...",
"status": "PENDING",
"message": null
}
| Field | Type | Description |
|---|---|---|
| trackingId | UUID | Poll with Section 8 (Document Status) or Section 9 (Get Invoice/Document Status) to follow progress. |
| status | String (Enum) | Initial queue status — see the DocumentProcessStatus table in Section 8. |
| message | String | null | Populated only if the request is rejected synchronously. |
400 - Bad Request
Returned when neither apiKey nor ublDto.companyId is present, or when the JSON payload fails KZ ESF validation (e.g. missing mandatory invoice type code).
403 - Forbidden
Returned when the authenticated user does not belong to the resolved company.
6. Presigned Upload for ESF XML POST
Purpose of Use: The POST /invoice/presign-upload endpoint returns a short-lived, company-scoped presigned S3 URL so an ERP can upload a large ESF V2 XML document directly to storage, bypassing the request body size limits of send-document-async. The returned key is then passed back as documentKey on send-document-async.
Kazakhstan-specific behavior: ZUGFeRD-family countries receive two upload slots (PDF + XML), because their flow merges a visual PDF with structured XML. Kazakhstan ESF has no PDF half — the ESF submission is the XML — so dataType: "KZ_ESF_V2" returns exactly one slot, for the XML, and places it directly under the document prefix rather than the pre-process prefix used by the merge flow.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/presign-upload |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
| Rate Limit | 2 requests / company, refilling 1 every minute |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/presign-upload' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"dataType": "KZ_ESF_V2",
"compId": "79499e36-6d45-4c7d-bc52-...",
"apiKey": null
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| dataType | String (Enum) | Yes | Must be KZ_ESF_V2 for Kazakhstan. Other accepted values (ZUGFERD, Factur-X variants) return two slots instead of one. |
| compId | String (UUID) | No* | Company to scope the upload to. One of compId / apiKey is required. |
| apiKey | String | No* | Resolves the company when compId is omitted. |
Responses
200 - Presigned URL Generated
{
"uploads": [
{
"fileType": "XML",
"key": "tmp/document/79499e36-6d45-4c7d-bc52-.../a1b2c3d4.xml",
"uploadUrl": "https://<bucket>.s3.amazonaws.com/tmp/document/...?X-Amz-Signature=..."
}
]
}
| Field | Type | Description |
|---|---|---|
| uploads | Array<Object> | One slot for KZ, two for ZUGFeRD-family types. |
| uploads[].fileType | String (Enum) | XML for Kazakhstan. |
| uploads[].key | String | The S3 object key. Pass this value as documentKey on send-document-async once the upload completes. |
| uploads[].uploadUrl | String | Presigned PUT URL, valid for 15 minutes. Upload the raw XML bytes directly to this URL. |
400 - Bad Request
Returned when dataType is not one of KZ_ESF_V2, ZUGFERD, or a Factur-X type.
429 - Too Many Requests
Returned when a company has already made 2 presign requests within the current refill window (1 token refilled per minute).
7. Generate PDF POST
Purpose of Use: This API endpoint generates a human-readable PDF from Kazakhstan ESF (ЭСФ) invoice XML (type: KZ_ESF_V2). The Base64-encoded ESF XML is transformed into HTML by the dedicated Kazakhstan ESF XSLT template, which renders the ESF document itself rather than a UBL conversion. The HTML is then converted into a PDF with iText 7. Bundled Unicode fonts make Cyrillic and Kazakh characters render correctly. The XML is not embedded in the PDF. The PDF is a visual copy only; the legally binding document is the ESF filed with the KGD through IS ESF. Supplying country (KZ) with vatNumber (BIN/IIN), or companyId, matches the company and renders the labels in its language setting (Kazakh, Russian or English). Without a match, the labels default to English. Designed for visualizing, printing and archiving ESF invoices in ERP integrations.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/generate/pdf |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authentication | R-Auth header (JWT Bearer Token) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/generate/pdf' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJNTU0iLCJzdWIiOiJwNjR9.IpGPX...' \
--data '{
"base64XML": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KC...",
"country": "KZ",
"type": "KZ_ESF_V2",
"vatNumber": "123456789012"
}'
Request Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| base64XML | String | Yes | Base64-encoded ESF V2 XML. |
| type | Enum (DataType) | Yes | Invoice format type — KZ_ESF_V2 for Kazakhstan. |
| country | Enum (Country) | No | KZ for Kazakhstan. When used together with vatNumber, company matching is performed to add logo and language settings to the PDF. |
| vatNumber | String | No | BIN/IIN of the invoicing company. When used together with country, it matches against the company record in the system. |
Valid Values for type Parameter
| Value | Description | XSLT Group |
|---|---|---|
| KZ_ESF_V2 | Kazakhstan ESF v2 format — the only value a Kazakhstan company should send. | KZ_ESF_V2 |
Shared enum: type also accepts every other country's format codes (XRechnung, ZUGFeRD, Factur-X, KSeF, etc.), each rendered by its own XSLT group — they are not applicable to a Kazakhstan company and are omitted here.
country Parameter
| Country Code | Country | PDF Language |
|---|---|---|
| KZ | Kazakhstan | Kazakh (KK) |
| Any other value, or omitted | — | English (EN) |
Note: The PDF stylesheet for KZ_ESF_V2 renders in Kazakh, Russian or English depending on the matched company's mailLanguage (Section 2) — passing country: "KZ" only decides whether company matching (logo, language) is attempted at all.
Responses
200 - Successful Response
| Property | Value |
|---|---|
| HTTP Status | 200 |
| Content-Type | application/octet-stream |
| Body | Binary PDF data (byte array) |
%PDF-1.7
%����
1 0 obj
<<
/Pages 2 0 R
/Type /Catalog
/Names 21 0 R
/Metadata 27 0 R
>>
endobj
5 0 obj
<<
400 - Bad Request
Trigger Condition: When the XML data is invalid, Base64 cannot be decoded, XSLT transformation fails, or any error occurs during iText PDF generation.
{
"errorMessage": "PDF convert error: [detail message]",
"errorType": "PDF_CONVERT_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}
Possible Detail Messages:
- PDF convert error: PDF conversion failed due to an unexpected error — XSLT template not found or unexpected error during HTML-to-PDF conversion
- PDF convert error: Illegal base64 character — The base64XML field is not in valid Base64 format
- PDF convert error: [XSLT transformation error]` — XML structure does not match the expected format
400 - Bad Request — Invalid Parameter
Trigger Condition: When an invalid enum value is sent for the type field or required fields are missing.
{
"errorMessage": "Invalid argument! Argument: type",
"errorType": "INVALID_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}
400 - Bad Request — Invalid PDF Type
Trigger Condition: When the submitted type value is an unsupported format for PDF conversion.
{
"errorMessage": "Invalid PDF type",
"errorType": "INVALID_PDF_TYPE",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}
400 - Bad Request — Empty XML Data
Trigger Condition: When the base64XML field is sent as null or empty.
{
"errorMessage": "Data XML cannot be NULL!",
"errorType": "NULL_DATA_XML",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}
401 - Unauthorized
Trigger Condition: When the R-Auth header is missing, the JWT token has expired, or an invalid token is provided.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 401,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}
500 - Internal Server Error
Trigger Condition: When an unexpected server error occurs (XSLT file cannot be loaded, insufficient memory, etc.).
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 500,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}
Error Codes and Response Details
The following errors are specific to this endpoint. All error responses follow the ExceptionResponse format:
Error Response Structure
| Field Name | Type | Description |
|---|---|---|
| errorMessage | String | Detailed description of the error |
| errorType | String | Error type identifier |
| errorTitle | String | HTTP status name (BAD_REQUEST, INTERNAL_SERVER_ERROR, etc.) |
| errorId | String | Correlation ID (for log tracing) |
| status | Integer | HTTP status code (400, 500, etc.) |
| timestamp | String (ISO 8601) | Time when the error occurred |
| path | String | Requested URL path |
8. Document Status GET
Purpose of Use: The GET /invoice/document-status/{trackingId} endpoint is used to query the processing status of documents (invoices, waybills, etc.) that were submitted asynchronously.
When a document is submitted through any of the send-document-async, send-document-async-json, send-by-file-async, or send-portal-new-async endpoints, the system immediately returns a trackingId and begins processing the document in the background.
Polling stops when the status becomes COMPLETED or FAILED.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/document-status/{trackingId} |
| Method | GET |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/document-status/{trackingId}' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
}'
Request Parameters
Path Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| trackingId | UUID | Yes | The tracking identifier returned from an asynchronous document submission. This is the trackingId value included in the response of send-document-async, send-document-async-json, send-by-file-async, or send-portal-new-async endpoints. |
Header Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| R-Auth | String (JWT) | Yes | User authentication token. A JWT signed with the HS512 algorithm. The payload carries userId, companyId, authorities, and userType information. |
| Accept | String | No | Response media type. Default: / |
Responses
200 - Successful Response
{
"trackingId": "dd240417-5896-4577-ae51-...",
"companyId": "79499e36-6d45-4c7d-bc52-...",
"direction": "OUTGOING",
"documentType": "KZ_ESF_V2",
"waybillType": null,
"source": "ERP",
"target": null,
"status": "COMPLETED",
"filename": null,
"invoiceNumber": "00900023888",
"documentId": "b34afc0b-4f5d-4670-910c-...",
"sendingResult": null,
"errorType": null,
"createdAt": "2026-09-16T07:25:50",
"statusUpdatedAt": "2026-09-16T07:26:00",
"completedAt": "2026-09-16T07:26:05",
"errors": null,
"additionalData": {
"kgdInvoiceId": 22116203282...,
"esfStatus": "KZ_CREATED"
}
}
Success Response Field Descriptions
| Field | Type | Description |
|---|---|---|
| trackingId | UUID | Unique tracking identifier for the document processing |
| companyId | UUID | Unique identifier of the company the document belongs to |
| direction | String (Enum) | Document direction: INCOMING or OUTGOING |
| documentType | String (Enum) | Document format — KZ_ESF_V2 for Kazakhstan |
| waybillType | String (Enum) | Waybill type. Only populated for waybill operations |
| source | String (Enum) | Source platform the document was submitted from (e.g., ERP, PORTAL) |
| target | String (Enum) | null | Target platform for the document |
| status | String (Enum) | Current processing status: PENDING, PROCESSING, COMPLETED, FAILED, SENDING_FAILED, PERMANENT_FAILED |
| filename | String | Name of the processed file |
| invoiceNumber | String | null | Invoice number assigned to the document. Populated when processing completes |
| documentId | UUID | null | Unique system identifier of the created document. Populated when processing completes |
| sendingResult | String | null | Sending result (e.g., SUCCESS). Populated when processing completes |
| errorType | String (Enum) | null | Error category when an error occurs. Null for successful operations |
| errors | Object | null | Error details. Variable type: can be List<ValidationError>, List<String>, or String |
| additionalData | Object | KZ-specific additional metadata. For an ESF: kgdInvoiceId (the provider's numeric invoice id) and esfStatus (the raw ESF status, see Section 10). For SNT, AVR and U-Form keys see "Results by document type" below. Carries statusSyncPaused / statusSyncPausedReason while status updates are paused (see Status credit in the Introduction). |
| createdAt | DateTime | Timestamp when the processing record was created (ISO 8601) |
| statusUpdatedAt | DateTime | Timestamp when the status was last updated (ISO 8601) |
| completedAt | DateTime | null | Timestamp when processing completed. Null while processing is ongoing |
Parameter Value Reference
DocumentProcessStatus — Possible Status Values
| Value | Description |
|---|---|
| PENDING | Document is queued, processing has not started yet |
| PROCESSING | Document is actively being processed (conversion, validation, sending, etc.) |
| COMPLETED | Document processing completed successfully |
| FAILED | An error occurred during document processing (may be retried) |
| SENDING_FAILED | Document was created but failed during the sending phase |
| PERMANENT_FAILED | Document processing permanently failed (will not be retried) |
DocumentType — Document Direction
| Value | Description |
|---|---|
| INCOMING | Incoming document |
| OUTGOING | Outgoing document |
DataType — Document Format (Relevant to Kazakhstan)
| Value | Description |
|---|---|
| KZ_ESF_V2 | Kazakhstan ESF v2 format — the only value a Kazakhstan company will see here. |
Shared enum: documentType also carries every other country's format codes (XRechnung, ZUGFeRD, Peppol BIS, KSeF, etc.) since this field is shared across the whole platform — not applicable to Kazakhstan.
WaybillDataType — Waybill Type (Relevant to Kazakhstan)
| Value | Description |
|---|---|
| KZ_SNT | SNT sent with waybillType = KZ_SNT |
| KZ_AWP | AVR sent with waybillType = KZ_AWP |
A U-Form sent with warehouseDocumentType has neither documentType nor waybillType set.
Results by document type
| Document | documentId | invoiceNumber | additionalData |
|---|---|---|---|
| ESF (KZ_ESF_V2) | Docnova invoice id | ESF number | kgdInvoiceId, esfStatus |
| SNT (KZ_SNT) | null — no Docnova SNT record is kept | SNT number | kgdSntId (KGD's SNT id; use it on the /snt/* endpoints) |
| AVR (KZ_AWP) | Docnova AVR record id (the id of GET /api/awp/{id}) | AVR number | kgdAwpId, awpStatus, and kgdRegistrationNumber once KGD has given one |
| U-Form (warehouseDocumentType) | Docnova U-Form id (the id of /kz/vwh/internal/uform/{id}) | U-Form number | kgdRegistrationNumber once KGD has given one |
On FAILED, errors carries KGD's or Docnova's message (for an AVR the same text the AVR section lists as errorMessage; the errorType code is not returned separately here).
⚠️ KGD_OUTCOME_UNKNOWN: When an SNT or AVR ends FAILED and the first entry of errors is KGD_OUTCOME_UNKNOWN, Docnova could not learn KGD's answer and the document may already be registered at KGD. Do not resend it (an AVR must not be resent under a new number); contact Docnova. A resend of the same AVR number is refused with DUPLICATE_AWP.
Sections 9 and 10 read the Docnova invoice record, so they apply to ESF invoices only. Follow SNT, AVR and U-Form submissions with this endpoint; after completion, follow an AVR with GET /api/awp/{id} and a U-Form with the VWH UForm endpoints.
ErrorType — Error Types Specific to This Endpoint
| Value | Message |
|---|---|
| INVOICE_PROCESS_NOT_FOUND | Tracking ID not found |
| VALIDATION_FAILED | Validation failed! |
| INVOICE_NULL_COULD_NOT_SAVE | Invoice is NULL and/or could not be saved! |
| INVOICE_CREATION_FAILED | Invoice creation failed! |
| INVOICE_SENDING_FAILED | Invoice sending failed: {details} |
404 - Not Found
Returned when the provided trackingId does not exist in the database.
Response Body: null (body is empty)
| Detail | Description |
|---|---|
| HTTP Status | 404 Not Found |
| Response Body | null (body is empty) |
| Trigger | No DocumentProcessEntity record matches the given trackingId in the database |
| Internal Error Type | INVOICE_PROCESS_NOT_FOUND — "Tracking ID not found" |
| Resolution | Verify the trackingId value is correct. Use the value returned in the response of the async submission endpoint |
401 - Unauthorized
Returned when the R-Auth header is missing, contains an invalid JWT token, or the token has expired.
{
"status": 401,
"error": "Unauthorized",
"message": "Full authentication is required to access this resource"
}
| Detail | Description |
|---|---|
| HTTP Status | 401 Unauthorized |
| Trigger | JWT token is missing, malformed, expired, or signature verification failed |
| Resolution | Send a valid, non-expired JWT token in the R-Auth header |
500 - Internal Server Error
Returned when an unexpected server error occurs during the status query.
Response Body: null (body is empty)
| Detail | Description |
|---|---|
| HTTP Status | 500 Internal Server Error |
| Response Body | null (body is empty) |
| Trigger | Database connection failure, entity conversion error, or other unexpected runtime exceptions |
| Resolution | Check server logs. Contact the support team if the issue persists |
Status-Based Response Examples
PENDING — Queued for Processing
{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": null,
"documentType": "KZ_ESF_V2",
"status": "PENDING",
"documentId": null,
"invoiceNumber": null,
"sendingResult": null,
"errorType": null,
"errors": null,
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:00",
"completedAt": null
}
PROCESSING — Currently Processing
{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "KZ_ESF_V2",
"status": "PROCESSING",
"documentId": "f47ac10b-58cc-4372-a567-...",
"invoiceNumber": "00900023888",
"sendingResult": null,
"errorType": null,
"errors": null,
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:20",
"completedAt": null
}
FAILED — Processing Failed (Validation Error)
{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": null,
"documentType": "KZ_ESF_V2",
"status": "FAILED",
"documentId": null,
"invoiceNumber": null,
"sendingResult": null,
"errorType": "VALIDATION_FAILED",
"errors": [
{
"field": "invoiceNumber",
"message": "Invoice number is required"
},
{
"field": "issueDate",
"message": "Issue date format is invalid"
}
],
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:15",
"completedAt": "2025-06-15T10:30:15"
}
FAILED — Processing Failed (General Error)
{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "KZ_ESF_V2",
"status": "FAILED",
"documentId": null,
"invoiceNumber": null,
"sendingResult": null,
"errorType": "INVOICE_NULL_COULD_NOT_SAVE",
"errors": [
"Invoice is NULL and/or could not be saved! XML parsing error at line 42"
],
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:12",
"completedAt": "2025-06-15T10:30:12"
}
SENDING_FAILED — Sending Failed
{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "KZ_ESF_V2",
"status": "SENDING_FAILED",
"documentId": "f47ac10b-58cc-4372-a567-...",
"invoiceNumber": "00900023888",
"sendingResult": null,
"errorType": "INVOICE_SENDING_FAILED",
"errors": [
"Invoice sending failed: ESF (IS ESF) service unreachable"
],
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:31:00",
"completedAt": "2025-06-15T10:31:00"
}
COMPLETED — With KZ-Specific Metadata
{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "KZ_ESF_V2",
"status": "COMPLETED",
"documentId": "f47ac10b-58cc-4372-a567-...",
"invoiceNumber": "00900023888",
"sendingResult": "SUCCESS",
"errorType": null,
"errors": null,
"additionalData": {
"kgdInvoiceId": 22116203282,
"esfStatus": "KZ_CREATED"
},
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:31:30",
"completedAt": "2025-06-15T10:31:30"
}
9. Get Invoice/Document Status GET
Purpose of Use: This endpoint is used to query the real-time processing status of an invoice/document by using the trackingId returned from an asynchronous document submission request.
After an invoice or document is submitted through an async flow, the first response may only contain a trackingId. This endpoint allows the client to follow the internal processing lifecycle of that document, including whether it is queued, processing, failed, or completed.
Once a documentId has been assigned to the document, this endpoint also returns invoice-level status information such as invoiceStatus and invoiceStatusDate. If the document has not yet been assigned a final documentId, those fields may be null, and only the process-level status fields should be used.
The request requires that the authenticated user in the R-Auth JWT has authority over the queried companyId.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/get-document-status-by-tracking |
| Method | GET |
| Content-Type | None — query parameters only, no request body |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth: {{jwt_token}} |
Example Request
curl -X GET 'https://api-stage.docnova.ai/invoice/get-document-status-by-tracking?companyId={{company_uuid}}&trackingId={{tracking_uuid}}' \
-H 'accept: */*' \
-H 'R-Auth: {{jwt_token}}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | String (UUID) | Yes | Unique identifier of the company that the queried tracking record belongs to. The requesting user must hold a role in this company. |
| trackingId | String (UUID) | Yes | The tracking identifier returned in the response of the document's asynchronous submission request. The document status is looked up via this identifier. |
Notes
- The
R-Authheader is mandatory. - The user in the JWT must have a role in the company matching
companyId. - If
trackingIdis not associated withcompanyId, for example when trying to access a record belonging to another company, a401 Unauthorizedresponse is returned. - If the tracking process is found but no
documentIdhas been assigned yet, only the process-level status fields are returned.
Responses
200 - Successful Response
{
"trackingId": "{{tracking_uuid}}",
"documentId": "{{document_uuid}}",
"invoiceStatus": "KZ_DELIVERED",
"invoiceStatusDate": "2026-01-15T12:00:00",
"processStatus": "COMPLETED",
"processStatusUpdatedAt": "2026-01-15T12:00:00"
}
Description: Request succeeded. If the document has not yet been assigned a documentId, the documentId, invoiceStatus, and invoiceStatusDate fields are null, and only processStatus / processStatusUpdatedAt are meaningful.
Response Fields
| Field | Type | Description |
|---|---|---|
| trackingId | String (UUID) | Echoes the trackingId sent in the request. Always populated. |
| documentId | String (UUID) | Populated once the document is assigned a final ID. null if the document has not yet been assigned. |
| invoiceStatus | String (Enum) | Populated once documentId is assigned. Contains the invoice's country/channel-specific final status. null if documentId is not yet assigned. |
| invoiceStatusDate | String (ISO 8601) | Timestamp of the last update to invoiceStatus. null if documentId is not yet assigned. |
| processStatus | String (Enum) | Status of the document's own processing pipeline. Always populated, even before documentId is assigned. |
| processStatusUpdatedAt | String (ISO 8601) | Timestamp of the last update to processStatus. Always populated. |
| statusSyncPaused | Boolean | true while KGD status updates for the document are paused because the company has no credit left (see Status credit in the Introduction). Omitted otherwise. |
| statusSyncPausedReason | String | Why updates are paused. Omitted together with statusSyncPaused. |
Parameter Values Reference Table
processStatus Values
| Value | Description |
|---|---|
| PENDING | Process has not started yet; queued. |
| PROCESSING | Document is currently being processed. |
| FAILED | Processing failed; may be retried. |
| SENDING_FAILED | An error occurred during the sending stage. |
| PERMANENT_FAILED | Permanent failure; will not be retried. |
| COMPLETED | Process completed successfully. |
invoiceStatus Values (Relevant to Kazakhstan)
For a Kazakhstan ESF invoice, invoiceStatus is always one of the KZ_* values listed in Section 10's status table — the same shared InvoiceStatus enum, scoped to Kazakhstan.
| Value | Description |
|---|---|
| CREATED | Generic: invoice/document has been created (used before a country-specific status is assigned). |
| CANCELED | Generic: canceled. |
| DELETED | Generic: deleted. |
| CREDIT_BLOCKED | Generic: payment blocked due to credit limit. |
Shared enum: invoiceStatus also carries statuses specific to other countries' formats and channels (ZUGFeRD, KSeF, Peppol AS4, OCR pipeline, etc.) — not applicable to Kazakhstan.
All error responses share the following structure:
{
"errorMessage": "<human-readable message>",
"errorType": "<error type key>",
"errorTitle": "<HTTP status name>",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/get-document-status-by-tracking"
}
400 - Bad Request
Tracking ID Not Found
{
"errorMessage": "Tracking ID not found",
"errorType": "INVOICE_PROCESS_NOT_FOUND",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/get-document-status-by-tracking"
}
Description: An ApiError(INVOICE_PROCESS_NOT_FOUND) is thrown when the trackingId is not found in the database.
Note: Although Swagger annotation documents this case as 404, the code currently calls withStatus() on this exception, so RestExceptionHandler returns the default 400 Bad Request.
401 - Unauthorized
{
"errorMessage": "User is not authorized for this operation",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/get-document-status-by-tracking"
}
Trigger: The user in the R-Auth JWT has no role or authority in the given companyId, or the trackingId belongs to a different company than the given companyId.
500 - Internal Server Error
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/get-document-status-by-tracking"
}
Trigger: An unexpected server-side error occurs.
This may happen because of a database connectivity issue, an unhandled exception, or another server-side runtime error.
10. Get Document Status GET
Purpose of Use: The GET /invoice/get-document-status/{documentId} endpoint returns the current shared InvoiceStatus of a document that already has a document ID (i.e. processing has completed and an invoice record exists). For Kazakhstan, the returned status is one of the KZ_* values mapped from the ESF status (see table below).
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/get-document-status/{documentId} |
| Method | GET |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/get-document-status/b34afc0b-4f5d-4670-910c-...' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
Path Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| documentId | UUID | Yes | The shared invoice identifier (the uuid/documentId returned by a creation or status endpoint). |
Responses
200 - Successful Response
{
"status": "KZ_DELIVERED",
"statusDate": "2026-09-16T07:26:05"
}
| Field | Type | Description |
|---|---|---|
| status | String (Enum) | Shared InvoiceStatus. For Kazakhstan, one of the KZ_* values below. |
| statusDate | DateTime | Timestamp of the last confirmed status change (ISO 8601). |
| statusSyncPaused | Boolean | true while KGD status updates for the document are paused because the company has no credit left (see Status credit in the Introduction). Omitted otherwise. |
| statusSyncPausedReason | String | Why updates are paused. Omitted together with statusSyncPaused. |
InvoiceStatus — Kazakhstan ESF Values
| ESF Status | Shared InvoiceStatus |
|---|---|
| IN_QUEUE | KZ_IN_QUEUE |
| IN_PROCESSING | KZ_IN_PROCESSING |
| CREATED | KZ_CREATED |
| DELIVERED | KZ_DELIVERED |
| CANCELED | KZ_CANCELED |
| CANCELED_BY_OGD | KZ_CANCELED_BY_OGD |
| CANCELED_BY_SNT_DECLINE | KZ_CANCELED_BY_SNT_DECLINE |
| CANCELED_BY_SNT_REVOKE | KZ_CANCELED_BY_SNT_REVOKE |
| REVOKED | KZ_REVOKED |
| IMPORTED | KZ_IMPORTED |
| DRAFT | KZ_DRAFT |
| FAILED | KZ_FAILED |
| DELETED | KZ_DELETED |
| DECLINED | KZ_DECLINED |
| SEND_TO_ISGO | KZ_SENT_TO_ISGO |
| WAIT_BIOMETRICS_VERIFICATION | KZ_WAIT_BIOMETRICS_VERIFICATION |
| FAILED_BIOMETRICS_VERIFICATION | KZ_FAILED_BIOMETRICS_VERIFICATION |
| DELETED_BIOMETRICS_VERIFICATION | KZ_DELETED_BIOMETRICS_VERIFICATION |
| WAITING_CUSTOMER_CONFIRMATION | KZ_WAITING_CUSTOMER_CONFIRMATION |
| WAITING_CUSTOMER_REVOKE_CONFIRMATION | KZ_WAITING_CUSTOMER_REVOKE_CONFIRMATION |
Local-only states: Three additional values are not official ESF statuses — they describe the local submission's own lifecycle: KZ_SUBMISSION_PENDING (reserved, not yet sent), KZ_SUBMISSION_FAILED (failed before reaching ESF), and KZ_RECONCILIATION_REQUIRED (the provider's answer is unknown and is being reconciled). A document in KZ_DELIVERED is not necessarily in its final state — it can still move to a CANCELED/REVOKED family status later; poll Section 9 (Get Invoice/Document Status) for the fully reconciled view when in doubt.
11. Search Document with Filter POST
Purpose of Use: The POST /invoice/search-documents endpoint is used to search for invoices and documents belonging to a specific company using various filtering criteria.
This API enables users to list documents associated with their company by applying filters such as date range, document direction (incoming or outgoing), invoice status, and document format (KZ_ESF_V2 for Kazakhstan). Results are returned with pagination support, and each page includes the total document count, tax exclusive total amount, and tax inclusive total amount.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/search-documents |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
Example Request
{
curl --location 'https://<BASE_URL>/invoice/search-documents' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"companyId": "<COMPANY_UUID>",
"documentType": "OUTGOING",
"endDate": "2026-01-31",
"page": 0,
"size": 10,
"startDate": "2026-01-01",
"status": "KZ_DELIVERED",
"type": "KZ_ESF_V2"
}'
}
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | UUID | Yes | Unique identifier of the company to search documents for |
| documentType | String (Enum) | No | Document direction filter. Used to filter incoming or outgoing documents |
| status | String (Enum) | No | Invoice status filter. Returns invoices in a specific status |
| type | String (Enum) | No | Document format type filter. Filters by invoice format |
| startDate | String (ISO Date) | No | Search start date. Format: YYYY-MM-DD |
| endDate | String (ISO Date) | No | Search end date. Format: YYYY-MM-DD |
| tin | String | No | Tax Identification Number filter |
| uit | String | No | UIT identifier filter |
| referenceDocument | String | No | Search by reference document number |
| page | Integer | No | Page number (0-based). Default: 0 |
| size | Integer | No | Number of records per page. Default: 50 |
Parameter Values
documentType Values
| Value | Description |
|---|---|
| INCOMING | Incoming documents (invoices sent by suppliers) |
| OUTGOING | Outgoing documents (invoices sent to customers) |
type Values (Relevant to Kazakhstan)
| Value | Group | Description |
|---|---|---|
| KZ_ESF_V2 | KZ_ESF_V2 | Kazakhstan ESF v2 format — the only value a Kazakhstan company should send. |
⚠️ Note: On this endpoint, the type filter only actively filters for the ZUGFeRD-family values (XRechnung, ZUGFeRD, Factur-X) — passing type: "KZ_ESF_V2" here does not filter results. To restrict a search to ESF invoices, rely on companyId (a Kazakhstan company only has KZ_ESF_V2 invoices) or filter client-side on the returned type field.
status Values (Relevant to Kazakhstan)
| Category | Value | Description |
|---|---|---|
| General | CREATED | Invoice created |
| PENDING | Awaiting processing | |
| CANCELED | Cancelled | |
| DELETED | Deleted | |
| SENT_VIA_EMAIL | Sent via email | |
| CREDIT_BLOCKED | Payment blocked due to credit limit (returns masked data) | |
| Kazakhstan ESF | KZ_CREATED, KZ_DELIVERED, KZ_CANCELED, … | Any of the KZ_* values in Section 10's status table |
Shared enum: status also carries statuses specific to other countries' formats and channels (ZUGFeRD, Peppol AS4, OCR pipeline, Romania ANAF, Poland KSeF, Malaysia LHDNM, Egypt ETA, Croatia eRacun, Denmark Nemhandel) — not applicable to Kazakhstan.
Responses
200 - Successful Response
{
"totalCount": 2,
"netTotal": 15000.00,
"total": 16800.00,
"invoiceList": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-...",
"companyId": "60ccd1a7-5348-47b2-9ef6-...",
"userId": "user-uuid",
"customerName": "Buyer LLP",
"supplierName": "Example Company LLP",
"supplierId": "supplier-uuid",
"supplierVat": "123456789012",
"status": "KZ_DELIVERED",
"invoiceNumber": "00900023888",
"taxExclusiveAmount": 15000.00,
"taxInclusiveAmount": 16800.00,
"lineExtensionAmount": 15000.00,
"payableAmount": 16800.00,
"allowanceTotalAmount": 0.00,
"currency": "KZT",
"createdTime": "2026-01-15T10:30:00",
"localCreatedTime": "2026-01-15T16:30:00",
"issueDate": "2026-01-15",
"deliveryDate": "2026-01-20",
"dueDate": "2026-02-15",
"supplierCountryCode": "KZ",
"supplierEndpoint": null,
"customerId": "customer-uuid",
"customerVat": "987654321098",
"customerEndpoint": null,
"customerCountryCode": "KZ",
"typeCode": "380",
"documentType": "OUTGOING",
"errorMessage": null,
"lastUpdatedTime": "2026-01-15T10:30:00",
"localLastUpdatedTime": "2026-01-15T16:30:00",
"type": "KZ_ESF_V2",
"source": "PORTAL",
"sendViaPeppol": false,
"statusTime": "2026-01-15T10:30:00",
"localStatusTime": "2026-01-15T16:30:00",
"fileName": "invoice_001.xml",
"ocrParser": null,
"paymentDetails": null,
"profileType": null,
"isActive": true,
"countrySpecificData": null
}
]
}
Successful Response Field Descriptions
Top-Level Fields
| Field | Type | Description |
|---|---|---|
| totalCount | Long | Total number of documents matching the filters |
| netTotal | Double | Tax-exclusive total amount (excludes CREDIT_BLOCKED) |
| total | Double | Tax-inclusive total amount (excludes CREDIT_BLOCKED) |
| invoiceList | Array<Invoice> | List of invoice objects |
Invoice Object Fields
| Field | Type | Description |
|---|---|---|
| id | String (UUID) | Unique identifier of the invoice |
| companyId | String (UUID) | Company ID the invoice belongs to |
| userId | String (UUID) | User ID who created the invoice |
| customerName | String | Customer (buyer) name |
| supplierName | String | Supplier (seller) name |
| supplierId | String | Supplier ID |
| supplierVat | String | Supplier VAT number |
| status | String (Enum) | Current invoice status |
| invoiceNumber | String | Invoice number |
| taxExclusiveAmount | Double | Tax-exclusive amount |
| taxInclusiveAmount | Double | Tax-inclusive amount |
| lineExtensionAmount | Double | Line items total amount |
| payableAmount | Double | Amount payable |
| allowanceTotalAmount | Double | Total allowance/discount amount |
| currency | String | Currency code (ISO 4217) — KZT for a Kazakhstan ESF invoice |
| createdTime | String (DateTime) | Creation timestamp (UTC) |
| localCreatedTime | String (DateTime) | Creation timestamp (local time) |
| issueDate | String (Date) | Invoice issue date |
| deliveryDate | String (Date) | Delivery date |
| dueDate | String (Date) | Due date |
| supplierCountryCode | String | Supplier country code (ISO 3166-1 alpha-2) |
| supplierEndpoint | String | null | Supplier Peppol endpoint — null for Kazakhstan (ESF does not use Peppol) |
| customerId | String | Customer ID |
| customerVat | String | Customer VAT number (BIN/IIN for Kazakhstan) |
| customerEndpoint | String | null | Customer Peppol endpoint — null for Kazakhstan (ESF does not use Peppol) |
| customerCountryCode | String | Customer country code |
| typeCode | String | Invoice type code (e.g., 380=Invoice, 381=Credit Note) |
| documentType | String (Enum) | Document direction: INCOMING or OUTGOING |
| errorMessage | String | Error message (if any) |
| lastUpdatedTime | String (DateTime) | Last update timestamp (UTC) |
| localLastUpdatedTime | String (DateTime) | Last update timestamp (local time) |
| type | String (Enum) | Document format type (DataType) |
| source | String (Enum) | Invoice source (PORTAL, ERP, PEPPOL, EMAIL, etc.) |
| sendViaPeppol | Boolean | Whether sent via Peppol |
| statusTime | String (DateTime) | Status change timestamp (UTC) |
| localStatusTime | String (DateTime) | Status change timestamp (local time) |
| fileName | String | File name |
| ocrParser | String (Enum) | OCR parser type |
| paymentDetails | Object | Payment details (null for certain statuses) |
| profileType | String (Enum) | null | ZUGFeRD profile type (BASIC, EN16931, EXTENDED) — null for Kazakhstan (ESF v2 is not a ZUGFeRD profile) |
| isActive | Boolean | Whether the invoice is active |
| countrySpecificData | Object | Country-specific additional data |
Note: Invoices with CREDIT_BLOCKED status are masked — only id, companyId, documentType, type,invoiceNumber ,supplierName,supplierVat , status and isActive fields are returned; all other fields are null.
400 - Bad Request
Returned when an invalid parameter value is provided (e.g., incorrect enum value, malformed UUID format).
{
"errorMessage": "Invalid value 'INVALID_STATUS' for parameter 'status'",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-abc123-def456",
"status": 400,
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/search-documents"
}
Error Response Fields
| Field | Type | Description |
|---|---|---|
| errorMessage | String | Human-readable error description |
| errorType | String | Error type code |
| errorTitle | String | HTTP status name |
| errorId | String | Correlation ID (for log tracing) |
| status | Integer | HTTP status code |
| timestamp | String (DateTime) | Error occurrence time |
| path | String | Request path |
401 - Unauthorized
Returned when an invalid, expired, or missing JWT token is provided.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"errorId": "corr-abc123-def456",
"status": 401,
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/search-documents"
}
Unauthorized Error Response Fields
| Field | Type | Description |
|---|---|---|
| errorMessage | String | Authorization error description |
| errorType | String | Fixed value: NOT_AUTHORITY |
| errorTitle | String | HTTP status name: UNAUTHORIZED |
| errorId | String | Correlation ID |
| status | Integer | 401 |
| timestamp | String (DateTime) | Error occurrence time |
| path | String | Request path |
500 - Internal Server Error
Returned in case of database connection errors, unexpected runtime exceptions, or other server-side failures.
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "corr-abc123-def456",
"status": 500,
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/search-documents"
}
Server Error Response Fields
| Field | Type | Description |
|---|---|---|
| errorMessage | String | General error message |
| errorType | String | RUNTIME_ERROR, IO_ERROR, or SERVER_ERROR |
| errorTitle | String | HTTP status name: INTERNAL_SERVER_ERROR |
| errorId | String | Correlation ID (for log tracing) |
| status | Integer | 500 |
| timestamp | String (DateTime) | Error occurrence time |
| path | String | Request path |
12. Search Documents v2 POST
Purpose of Use: The POST /invoice/v2/search-documents endpoint behaves identically to Section 11 (Search Document with Filter), with the same request body and filters, but enriches each INCOMING result with additional fields intended for white-label partner integrations and reconciliation tooling.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/v2/search-documents |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/v2/search-documents' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"companyId": "79499e36-6d45-4c7d-bc52-...",
"documentType": "INCOMING",
"type": "KZ_ESF_V2",
"invoiceSearchType": "CREATE_DATE",
"page": 0,
"size": 50
}'
Request Parameters
Identical to Section 11 (Search Document with Filter): companyId, tin, uit, status, documentType (INCOMING/OUTGOING), referenceDocument, startDate, endDate, page, size (max 200), type (DataType, e.g. KZ_ESF_V2), and invoiceSearchType (ISSUE_DATE / CREATE_DATE / DUE_DATE, default CREATE_DATE).
Responses
200 - Successful Response
Same envelope as Section 11, with each INCOMING invoice item additionally carrying:
{
"supplierPaymentAccount": {
"iban": "KZ123456789012345678",
"bic": "ABCDKZKZ",
"accountHolderName": "Supplier LLP"
},
"lineItems": [
{
"itemName": "Office supplies",
"quantity": 10,
"unitCode": "EA",
"unitPrice": 1500.00,
"netAmount": 15000.00,
"currency": "KZT",
"taxRatePercent": 12,
"taxAmount": 1800.00,
"taxCategoryCode": "S"
}
]
}
| Field | Type | Description |
|---|---|---|
| supplierPaymentAccount | Object | null | Extracted from the invoice's payment means, when present. |
| supplierPaymentAccount.iban | String | Supplier IBAN. |
| supplierPaymentAccount.bic | String | Supplier bank BIC/SWIFT code. |
| supplierPaymentAccount.accountHolderName | String | Name on the bank account. |
| lineItems | Array<Object> | null | One entry per invoice line, when the archived document could be parsed. |
| lineItems[].itemName | String | Line item description. |
| lineItems[].quantity | BigDecimal | Billed quantity. |
| lineItems[].unitCode | String | Unit of measure code. |
| lineItems[].unitPrice | BigDecimal | Price per unit. |
| lineItems[].netAmount | BigDecimal | Net line amount. |
| lineItems[].currency | String | ISO 4217 currency code. |
| lineItems[].taxRatePercent | BigDecimal | Tax rate applied to the line. |
| lineItems[].taxAmount | BigDecimal | Computed tax amount for the line. |
| lineItems[].taxCategoryCode | String | Tax category code. |
⚠️ Note: supplierPaymentAccount and lineItems are only returned for INCOMING invoices, and only when the original archived document could be parsed; both are null otherwise.
13. Retrieve Doc by ID and Type GET
Purpose of Use: The GET /invoice/get-document/{documentId}/{documentTypes} endpoint allows downloading a previously stored invoice or document in a specific format such as PDF, XML, or JSON.
The client provides the document UUID (documentId) and the desired output format (documentTypes). The API returns the document content as Base64 encoded data. This is mainly used in ERP integrations to programmatically fetch, view, archive, or store invoice documents.
When the requested format is pdf, the API returns the printable or viewable PDF file content as Base64 encoded data.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/get-document/{documentId}/{documentTypes} |
| Method | GET |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/get-document/{documentId}/pdf' \
--header 'Accept: */*' \
--header 'R-Auth: {auth-token}'
}'
Request Parameters
Path Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| documentId | String (UUID) | Yes | Unique identifier of the document. Must be in UUID v4 format. Example: 550e8400-e29b-41d4-a716-... |
| documentTypes | String (Enum) | Yes | Requested document format type. Multiple types can be separated by hyphen -. Example: PDF, XML |
Header Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| R-Auth | String (JWT) | Yes | Authentication token. JWT signed with HS512 algorithm. |
| Accept | String | No | Accepted response media type. Default: / |
documentTypes Parameter Values
| Value | Format Type | Description |
|---|---|---|
| FormatType.PDF | Returns Base64-encoded PDF representation of the invoice | |
| XML | FormatType.XML | Returns the Base64-encoded original ESF XML of the invoice |
| JSON | FormatType.JSON | Returns a Base64-encoded structured JSON representation of the invoice |
| PDF-XML | Multiple formats | Multiple formats can be requested simultaneously using hyphen separator |
| XML-PDF-JSON | Multiple formats | All three formats can be requested at once |
Note: JSON format is only supported for invoices processed by OCR (OCR_PARSED) or completed by MelAI (COMPLETED_BY_MELAI_AI).
Responses
200 - Successful Response
{
"documents": [
{
"file_type": "PDF",
"data": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC..."
}
]
}
Successful Response Field Descriptions
| Field Name | Type | Description |
|---|---|---|
| documents | List<Document> | List of documents in requested formats. Contains one Document object per format. |
| documents[].file_type | String (Enum) | Document format type. Possible values: PDF, XML, JSON |
| documents[].data | String (Base64) | Base64-encoded content of the document. When decoded for PDF, produces a valid PDF file. |
Multi-Format Response Example
{
"documents": [
{
"file_type": "XML",
"data": "PD94bWwgdmVy... (base64)"
},
{
"file_type": "PDF",
"data": "JVBERi0xLjQK... (base64)"
}
]
}
401 - Unauthorized
Returned when an invalid or missing R-Auth token is provided.
{
"errorMessage": "Authentication is required. Please complete the authentication process.",
"errorType": "AUTHENTICATION_REQUIRED",
"errorTitle": "UNAUTHORIZED",
"errorId": "corr-abc123",
"status": 401,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../pdf"
}
| Field | Description |
|---|---|
| errorMessage | Indicates that the authentication process must be completed. |
| errorType | AUTHENTICATION_REQUIRED Token is missing, expired, or invalid. |
| status | 401 |
400 - Bad Request
Returned when an invalid documentTypes value is provided.
{
"errorMessage": "Unsupported document type: DOCX",
"errorType": "INVALID_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-def456",
"status": 400,
"timestamp": "2026-02-11T14:31:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../docx"
}
| Field | Description |
|---|---|
| errorMessage | Specifies the unsupported document type and which type was invalid. |
| errorType | INVALID_ARGUMENT An invalid parameter was provided. |
| status | 400 |
400 - Bad Request
Returned when the document's OCR processing has not yet completed (waiting state).
{
"errorMessage": "Invoice is waiting for MelaAIParser. Please try again later",
"errorType": "INVALID_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-ghi789",
"status": 400,
"timestamp": "2026-02-11T14:32:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../json"
}
| Field | Description |
|---|---|
| errorMessage | Indicates the invoice has not been processed by MelaAI yet and should be retried later. |
| errorType | INVALID_ARGUMENT The invoice is not in a processable state currently. |
| status | 400 |
404 - Not Found
Returned when no document matches the provided UUID. Specifically occurs when JSON format is requested and the invoice is not found.
{
"errorMessage": "af6e8982-b791-4704-bc06-d4655faa4b4c Invoice not found!",
"errorType": "NOT_FOUND_INVOICE",
"errorTitle": "NOT_FOUND",
"errorId": "corr-jkl012",
"status": 404,
"timestamp": "2026-02-11T14:33:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../json"
}
| Field | Description |
|---|---|
| errorMessage | Returns a not found message along with the document UUID. |
| errorType | NOT_FOUND_INVOICE No matching invoice record exists in the database. |
| status | 404 |
500 - Internal Server Error
Returned when an unexpected error occurs (e.g., file cannot be retrieved from S3, PDF conversion fails).
{
"errorMessage": "Internal server error",
"errorType": "SERVER_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "corr-mno345",
"status": 500,
"timestamp": "2026-02-11T14:34:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../pdf"
}
| Field | Description |
|---|---|
| errorMessage | Generic server error message. |
| errorType | SERVER_ERROR An unexpected error occurred. |
| status | 500 |
Common Error Response Field Descriptions
| Field Name | Type | Description |
|---|---|---|
| errorMessage | String | Human readable description of the error |
| errorType | String | Programmatic classification code of the error |
| errorTitle | String (HttpStatus) | Text representation of the HTTP status code |
| errorId | String | Request correlation ID (for log tracking) |
| status | Integer | HTTP status code (numeric) |
| timestamp | String (ISO 8601) | Timestamp when the error occurred |
| path | String | Endpoint path where the error occurred |
| details | Map<String, Object> | Additional error details (if available) |
| validationErrors | List<ValidationError> | List of validation errors (if available) |
14. Search Processing History POST
Purpose of Use: The POST /invoice/document-process/search endpoint serves as the central monitoring and querying interface for all document processing activities within the system. Every document whether it is an invoice, credit note, or waybill that enters or leaves the platform passes through an asynchronous processing pipeline. This endpoint provides full visibility into that pipeline.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/document-process/search |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
| Required Authority | ADMIN, INCOMING_INVOICE_DISPLAY, or OUTGOING_INVOICE_DISPLAY (at least one) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/document-process/search?page=0&size=20&sort=createdAt,desc' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"companyId": "<COMPANY_UUID>",
"createdAt": {
"from": "2024-01-01",
"to": "2026-02-28"
}
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | UUID | Yes | Unique identifier of the company to search |
| direction | String (Enum) | No | Document direction filter (INCOMING or OUTGOING) |
| source | String (Enum) | No | Source system filter |
| filename | String | No | Exact match filter by filename |
| status | String (Enum) | No | Document processing status filter |
| createdAt | Object (DateRange) | No | Creation date range filter |
| createdAt.from | String (LocalDate) | No | Start date (inclusive). Format: yyyy-MM-dd. Must be past or present |
| createdAt.to | String (LocalDate) | No | End date (inclusive). Format: yyyy-MM-dd. Must be past or present |
Query Parameters (Pagination)
| Field | Type | Default | Description |
|---|---|---|---|
| page | Integer | 0 | Page number (0 indexed) |
| size | Integer | 20 | Number of records per page (max 100) |
| sort | String | createdAt,desc | Sort field and direction. Format: field,asc|desc |
Enum Value Reference
direction Values (Document Direction)
| Value | Description |
|---|---|
| INCOMING | Incoming document |
| OUTGOING | Outgoing document |
status Values (Processing Status)
| Value | Description |
|---|---|
| PENDING | Queued and waiting for processing |
| PROCESSING | Currently being processed |
| COMPLETED | Successfully completed |
| FAILED | Processing failed (retriable) |
| SENDING_FAILED | Failed at the sending stage |
| PERMANENT_FAILED | Permanently failed (will not be retried) |
source Values (Relevant to Kazakhstan)
| Value | Description |
|---|---|
| ERP | ERP integration |
| PORTAL | Web portal |
| PORTAL_OCR | Portal upload via OCR |
| EMAIL_OCR | OCR via email |
| SFTP | SFTP connection |
| SERVICE | Internal service — e.g. the KZ incoming ESF sync (the ESF section below) |
| HARVEST / SHOPIFY / AMAZON_SP / EBAY / HUBSPOT / LAZADA / STRIPE | Marketplace/accounting integrations, available regardless of country |
Shared enum: source also carries values for other countries' direct government/network integrations (PEPPOL, KSEF, ANAF, LHDNM, NEMHANDEL, RS_API, ETA, ERACUN) — not applicable to Kazakhstan.
documentType Values (Relevant to Kazakhstan)
| Value | Description |
|---|---|
| KZ_ESF_V2 | Kazakhstan ESF v2 — the only value a Kazakhstan company will see here. |
waybillType Values
⚠️ Not applicable to Kazakhstan: This field only carries Serbia/Romania waybill format codes. Kazakhstan waybills (SNT) are tracked through the dedicated /snt/* API (the SNT section below).
Responses
200 - Successful Response
{
"content": [
{
"trackingId": "a1b2c3d4-...",
"companyId": "60ccd1a7-...",
"direction": "INCOMING",
"documentType": "KZ_ESF_V2",
"waybillType": null,
"source": "ERP",
"target": null,
"status": "COMPLETED",
"filename": "invoice_2024_001.xml",
"invoiceNumber": "00900023888",
"documentId": "f5e6d7c8-...",
"sendingResult": "OK",
"errorType": null,
"errors": null,
"additionalData": null,
"createdAt": "2024-06-15T10:30:00",
"statusUpdatedAt": "2024-06-15T10:30:45",
"completedAt": "2024-06-15T10:31:00"
}
],
"totalElements": 150,
"totalPages": 8,
"number": 0,
"size": 20
}
Response Fields
| Field | Type | Description |
|---|---|---|
| content | Array<Object> | Page content (document processing records) |
| content[].trackingId | UUID | Processing tracking identifier |
| content[].companyId | UUID | Company identifier |
| content[].direction | String (Enum) | Document direction (INCOMING / OUTGOING) |
| content[].documentType | String (Enum) | Document format (see documentType enum table) |
| content[].waybillType | String (Enum) | null | Waybill type (only for waybill documents) |
| content[].source | String (Enum) | Source system of the document |
| content[].target | String (Enum) | null | Target system for the document |
| content[].status | String (Enum) | Current processing status |
| content[].filename | String | Original filename |
| content[].invoiceNumber | String | null | Invoice number |
| content[].documentId | UUID | null | Associated document identifier |
| content[].sendingResult | String | null | Sending result message |
| content[].errorType | String (Enum) | null | Error type code (on failed processes) |
| content[].errors | Object | null | Error details (validation errors, message list, or text) |
| content[].additionalData | Object | null | Country or document type specific metadata |
| content[].createdAt | String (DateTime) | Creation timestamp. Format: yyyy-MM-ddTHH:mm:ss |
| content[].statusUpdatedAt | String (DateTime) | Last status update timestamp |
| content[].completedAt | String (DateTime) | null | Completion timestamp (only when COMPLETED) |
| totalElements | Long | Total number of matching records |
| totalPages | Integer | Total number of pages |
| number | Integer | Current page number (0-indexed) |
| size | Integer | Number of records per page |
400 - Bad Request
Trigger: When the companyId field is sent as null in the request body (@NotNull validation) or when required fields are missing.
Scenario: Sending a request without providing companyId.
{
"errorMessage": "Document process required fields: companyId",
"errorType": "DOCUMENT_PROCESS_REQUIRED_FIELDS",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-8f2a1b3c",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}
400 - Bad Request
Trigger: When the request body JSON format is malformed, an invalid enum value is sent, or the date format is incorrect.
Scenario: Sending a value like "UNKNOWN_STATUS" that is not defined in the enum for the status field, or sending an invalid date like "2024-13-45" for the createdAt.from field.
{
"errorMessage": "Invalid request. Cannot deserialize value of type `DocumentProcessStatus` from String \"UNKNOWN_STATUS\"",
"errorType": "INVALID_REQUEST",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-4d5e6f7a",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}
401 - Unauthorized
Trigger: When the R-Auth header is not provided or the JWT token signature is invalid. This error is caught at the Spring Security filter chain and does not reach the RestExceptionHandler.
Scenario: Sending a request without the header or with a corrupted/tampered token.
{
"error": "Unauthorized",
"message": "Full authentication is required to access this resource",
"status": 401
}
401 - Unauthorized
Trigger: When the JWT token is valid but the user does not have any of the ADMIN, INCOMING_INVOICE_DISPLAY, or OUTGOING_INVOICE_DISPLAY authorities on the specified companyId. Thrown by AuthorizationService.checkAnyAuthorityByCompanyAndUser().
Scenario: Performing a search with a companyId for which the user has no access permissions.
{
"errorMessage": "User is not authorized for this operation",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"errorId": "corr-9a8b7c6d",
"status": 401,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}
498 - Token Expired
Trigger: When the JWT token has expired. Returned by CustomAuthenticationEntryPoint at the Spring Security filter level.
Scenario: Sending a request with an expired JWT token.
{
"errorMessage": "Your session has expired. Please login again.",
"errorType": "TOKEN_EXPIRED",
"errorTitle": "UNAUTHORIZED",
"status": null,
"timestamp": null,
"path": null
}
Note: Since this response is generated at the Security filter level, the timestamp, path, and status fields are not populated by enrichResponse and return null. A custom HTTP status code of 498 is used.
404 - Not Found
Trigger: When the provided companyId value is not found in the database. A NotFoundException is thrown by CompanyService.
Scenario: Sending a UUID as companyId that has been deleted or never existed.
{
"errorMessage": "Company not found!",
"errorType": "COMPANY_NOT_FOUND",
"errorTitle": "NOT_FOUND",
"errorId": "corr-1b2c3d4e",
"status": 404,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}
500 - Internal Server Error
Trigger: When an unexpected error occurs on the server side (database connection failure, NullPointerException, etc.). Caught by the RestExceptionHandler catch-all handler.
Scenario: Database access failure, unexpected runtime exception.
{
"errorMessage": "An unexpected error occurred",
"errorType": "SERVER_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "corr-5e6f7a8b",
"status": 500,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}
Response Structure Reference (ExceptionResponse)
| Field | Type | Description | Inclusion Condition |
|---|---|---|---|
| errorMessage | String | Human readable error description | Always |
| errorType | String | Machine readable error code (ErrorType enum name) | Always |
| errorTitle | String (HttpStatus) | HTTP status description (BAD_REQUEST, UNAUTHORIZED, etc.) | Always |
| errorId | String | Correlation ID (for log tracing) | If present in ThreadContext |
| status | Integer | HTTP status code (numeric) | Always |
| timestamp | String (DateTime) | Timestamp when the error occurred | By RestExceptionHandler |
| path | String | URI of the request | By RestExceptionHandler |
| data | String | Additional data information | If present (@JsonInclude NON_NULL) |
| details | Map<String, Object> | Additional detail information | If present (@JsonInclude NON_NULL) |
| validationErrors | Array<ValidationError> | Field level validation errors | If present (@JsonInclude NON_NULL) |
Note: The ExceptionResponse class uses @JsonInclude(JsonInclude.Include.NON_NULL). Therefore, fields with null values are excluded from the JSON response.
15. Mark Document Processing as Read PATCH
Purpose of Use: The PATCH /invoice/document-process/update/read endpoint flags one or more document-processing records (the same records returned by Section 14 (Search Processing History) and the status endpoints) as read or unread, for building an inbox-style unread counter in an ERP or portal integration. Failed documents are created as unread by default, to draw attention to them.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/document-process/update/read |
| Method | PATCH |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) |
Example Request
curl --location --request PATCH 'https://api-stage.docnova.ai/invoice/document-process/update/read' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"isRead": true,
"companyId": "79499e36-6d45-4c7d-bc52-...",
"trackingIds": ["dd240417-5896-4577-ae51-...", "ee351528-6907-4688-bf62-..."]
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| isRead | Boolean | Yes | Target read state to apply to every listed tracking ID. |
| companyId | UUID | Yes | Company the tracking IDs must belong to. |
| trackingIds | Array<UUID> | Yes | One or more document-processing tracking IDs to update. Must not be empty. |
Responses
200 - Read Status Updated
{
"isRead": true,
"companyId": "79499e36-6d45-4c7d-bc52-...",
"trackingIds": ["dd240417-5896-4577-ae51-...", "ee351528-6907-4688-bf62-..."]
}
403 - Forbidden
Returned when one or more of the given trackingIds do not belong to companyId.
404 - Not Found
Returned when none of the given trackingIds were found.
About this section: The endpoints below (/esf prefix) are Kazakhstan's native ESF integration layer — a direct, typed mapping of the government ESF SOAP service's own operations, distinct from the generic cross-country /invoice endpoints above. Every endpoint in this section:
- Requires the R-Auth JWT and an API key with a company already bound to it (restrictedCompanyId) — there is no compId/apiKey body parameter to select the company; it comes from the authenticated API key's own scope.
- Requires authority ADMIN or ERP_MANAGEMENT_API_KEY_GENERATE.
- Returns 403 AUTHORIZATION_FAILED if the API key has no company bound to it.
- Uses Long invoice IDs (the ESF service's own numeric identifier), not the shared platform's invoice UUID.
ESF
Электронды Шот-Фактура (ЭСФ) / Electronic Invoice-Facture (ESF) — Kazakhstan's primary e-invoice exchange with the KGD (State Revenue Committee). All endpoints below share the /esf prefix and the same company-bound API key authorization described in Authentication.
1. Enterprise Validation POST
Purpose of Use: The POST /esf/enterprise-validation endpoint validates a counterparty's banking/certificate identifiers against the government registry before an ESF invoice is created against them — catching a bad TIN, BIK or IIK up front instead of as a late ESF rejection.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/enterprise-validation |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/enterprise-validation' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"enterpriseKeyList": [
{
"tin": "123456789012",
"certificateSeries": "AB",
"certificateNum": "1234567",
"bik": "HSBKKZKX",
"iik": "KZ123456789012345678"
}
]
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| enterpriseKeyList | Array<Object> | Yes | One or more entities to validate. |
| enterpriseKeyList[].tin | String | Yes | Taxpayer Identification Number (ИИН/БИН). |
| enterpriseKeyList[].certificateSeries | String | No | E-signature certificate series. |
| enterpriseKeyList[].certificateNum | String | No | E-signature certificate number. |
| enterpriseKeyList[].bik | String | No | Bank identification code. |
| enterpriseKeyList[].iik | String | No | Individual identification code (bank account). |
Responses
200 - Successful Response
{
"resultList": {
"enterpriseValidationResult": [
{ "tin": "123456789012", "resultType": "SUCCESS" }
]
}
}
| Field | Type | Description |
|---|---|---|
| resultList.enterpriseValidationResult | Array<Object> | One result per requested key, in request order. |
| [].tin | String | Echoes the validated TIN. |
| [].resultType | String (Enum) | See values below. |
EnterpriseValidationResultType Values
| Value | Description |
|---|---|
| SUCCESS | All supplied identifiers are valid and consistent with the registry. |
| TIN_ABSENT | TIN/BIN not found in the registry. |
| CERTIFICATE_SERIES_OR_CERTIFICATE_NUM_ABSENT | Certificate series or number not found. |
| BIK_ABSENT | Bank identification code not found. |
| BANK_NOT_FOUND | No bank matches the given BIK. |
| IIK_ABSENT | Account identification code not found. |
2. Upload Invoice List (Sync) POST
Purpose of Use: The POST /esf/upload-invoice-list endpoint is the native ESF submission call — it submits one or more pre-signed ESF XML documents directly to the government service (synchronously) and returns, per document, whether it was accepted or declined. This is the lowest-level submission primitive; the generic /invoice endpoints in the section above are built on top of it.
⚠️ Note: Every document in invoiceUploadInfoList gets its own reservation, quota charge, and result — a rejection on one document never discards or retries the others in the same call.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/upload-invoice-list |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/upload-invoice-list' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"invoiceUploadInfoList": [
{
"invoiceBody": "<BASE64_ENCODED_ESF_V2_XML>",
"version": "InvoiceV2",
"signature": "<BASE64_ESF_SIGNATURE_MAX_400_CHARS>",
"signatureType": "COMPANY"
}
]
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| invoiceUploadInfoList | Array<Object> | Yes | One or more documents to submit. |
| invoiceUploadInfoList[].invoiceBody | String (Base64) | Yes | The ESF XML body, Base64-encoded. |
| invoiceUploadInfoList[].version | String (Enum) | No | InvoiceV1 or InvoiceV2 (default). |
| invoiceUploadInfoList[].signature | String | Yes | The e-signature over the invoice body, max 400 characters. |
| invoiceUploadInfoList[].signatureType | String (Enum) | Yes | COMPANY (company's own e-signature) or OPERATOR (an authorized operator signs on the company's behalf). |
Responses
200 - Successful Response
{
"acceptedSet": {
"standardResponse": [
{ "id": 22116203282, "num": "00900023888", "date": "2026-09-16" }
]
},
"declinedSet": {
"standardResponse": [
{ "num": "00900023889", "date": "2026-09-16", "errors": { "error": [ { "property": "seller.tin", "errorCode": "REQUIRED", "text": "Seller TIN is required" } ] } }
]
}
}
| Field | Type | Description |
|---|---|---|
| acceptedSet.standardResponse | Array<Object> | One entry per accepted document. |
| declinedSet.standardResponse | Array<Object> | One entry per rejected document, with the validation errors that caused the rejection. |
| [].id | Long | ESF's own numeric invoice ID. Present only in acceptedSet. Use this value as idList on the query/action endpoints below. |
| [].num | String | Invoice number, echoed from the XML. |
| [].date | String | Invoice date, echoed from the XML. |
| [].errors.error[].property | String | The XML field that failed validation, when present. |
| [].errors.error[].errorCode | String | ESF error code. |
| [].errors.error[].text | String | Human-readable error description. |
3. Query Updates POST
Purpose of Use: The POST /esf/query-updates endpoint is the recommended polling primitive for keeping a local system in sync with ESF: given the last event date/invoice ID the caller has already processed, it returns the next batch of invoices (new or changed) in event order.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/query-updates |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/query-updates' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"lastEventDate": "2026-09-16T07:00:00",
"lastInvoiceId": 22116203200,
"direction": "INBOUND",
"limit": 50,
"fullInfoOnStatusChange": false
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| lastEventDate | String | No | Resume point. Omit on the very first call to start from the beginning. |
| lastInvoiceId | Long | No | Tie-breaker for lastEventDate — advance past this invoice too. |
| direction | String (Enum) | No | INBOUND or OUTBOUND. |
| limit | Integer | No | Page size. |
| fullInfoOnStatusChange | Boolean | No | When true, includes the full invoice body on status-only changes too, not just on new invoices. |
Responses
200 - Successful Response
{
"lastEventDate": "2026-09-16T07:30:00",
"lastInvoiceId": 22116203282,
"lastBlock": true,
"invoiceInfoList": {
"invoiceInfo": [
{
"invoiceId": 22116203282,
"invoiceBody": "<BASE64_ESF_V2_XML>",
"registrationNumber": "KZ...",
"inputDate": "2026-09-16T07:25:50",
"lastUpdateDate": "2026-09-16T07:26:00",
"signatureValid": true,
"invoiceStatus": "DELIVERED",
"version": "InvoiceV2",
"signatureType": "COMPANY",
"certificate": "<BASE64_CERTIFICATE>"
}
]
}
}
| Field | Type | Description |
|---|---|---|
| lastEventDate / lastInvoiceId | — | Pass both back as-is on the next call to continue from here. |
| lastBlock | Boolean | true when this page is the last available page — keep polling at interval; false means more pages are ready now, call again immediately with the returned cursor. |
| invoiceInfoList.invoiceInfo | Array<Object> | The batch of updated invoices — see the InvoiceInfo fields below. |
InvoiceInfo Fields
| Field | Type | Description |
|---|---|---|
| invoiceBody | String (Base64) | The full ESF XML. |
| invoiceId | Long | ESF's numeric invoice ID. |
| registrationNumber | String | Government registration number, once assigned. |
| inputDate / deliveryDate / lastUpdateDate | DateTime | Lifecycle timestamps. |
| signatureValid | Boolean | Whether the e-signature validated successfully. |
| invoiceStatus | String (Enum) | See the InvoiceStatus table below. |
| cancelReason | String | Populated for canceled/declined/revoked invoices. |
| version | String (Enum) | InvoiceV1 / InvoiceV2. |
| signatureType | String (Enum) | COMPANY / OPERATOR. |
| certificate | String | The signer's certificate. |
| deadline | Object | Any statutory response deadline attached to the invoice, when applicable. |
| kogd | String | Tax authority code, when applicable. |
InvoiceStatus Values (ESF)
| Value | Description |
|---|---|
| IN_QUEUE | Queued |
| IN_PROCESSING | Processing |
| CREATED | Created |
| DELIVERED | Delivered |
| CANCELED | Canceled |
| CANCELED_BY_OGD | Canceled by tax authority for accounting purposes |
| CANCELED_BY_SNT_DECLINE | Canceled because the linked waybill (SNT) was declined |
| CANCELED_BY_SNT_REVOKE | Canceled because the linked waybill (SNT) was revoked |
| REVOKED | Revoked |
| IMPORTED | Imported from a legacy system |
| DRAFT | Draft |
| FAILED | Failed |
| DELETED | Deleted |
| DECLINED | Declined |
| SEND_TO_ISGO | Forwarded to ISGO (goods tracking) |
| WAIT_BIOMETRICS_VERIFICATION | Awaiting biometric identification |
| FAILED_BIOMETRICS_VERIFICATION | Biometric identification failed |
| DELETED_BIOMETRICS_VERIFICATION | Deleted before biometric identification completed |
| WAITING_CUSTOMER_CONFIRMATION | Awaiting recipient confirmation |
| WAITING_CUSTOMER_REVOKE_CONFIRMATION | Awaiting recipient confirmation of a revoke request |
4. Get Unread Invoices POST
Purpose of Use: The POST /esf/unread-invoices endpoint returns the invoices the company has not yet marked as read — a simpler alternative to Query Updates for building an inbox-style "new invoices" indicator.
Status credit: Each new status this endpoint reads from KGD is charged as described in Status credit (Introduction), and the status is stored on the invoice in the same call. When there is no unread invoice, KGD is not asked and nothing is charged. Without credit the call answers HTTP 400 LIFECYCLE_CREDIT_EXHAUSTED and KGD is not asked.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/unread-invoices |
| Method | POST |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/unread-invoices' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Responses
200 - Successful Response
Returns an array of InvoiceDTO objects (same shape as the Query Invoice response in the next section).
5. Set Read/Unread Invoices POST
Purpose of Use: The POST /esf/set-read-list endpoint marks one or more ESF invoices as read.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/set-read-list |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/set-read-list' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282, 22116203283] }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| idList | Array<Long> | Yes | ESF numeric invoice IDs to mark as read. |
Responses
200 - Successful Response
true
Returns a plain boolean indicating success.
6. Get Invoice Status List by ID POST
Purpose of Use: The POST /esf/get-invoice-status-list-by-id endpoint returns just the current status (not the full body) for a batch of invoice IDs — a lightweight way to refresh status for a list already held locally.
Status credit: Each new status this endpoint reads from KGD is charged as described in Status credit (Introduction). Without credit the call answers HTTP 400 LIFECYCLE_CREDIT_EXHAUSTED and KGD is not asked.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/get-invoice-status-list-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/get-invoice-status-list-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282, 22116203283] }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| idList | Array<Long> | Yes | ESF numeric invoice IDs to check. |
Responses
200 - Successful Response
[
{ "invoiceId": 22116203282, "status": "DELIVERED", "cancelReason": null }
]
| Field | Type | Description |
|---|---|---|
| invoiceId | Long | ESF numeric invoice ID. |
| status | String (Enum) | See the InvoiceStatus table in the previous section. |
| cancelReason | String | null | Populated for canceled/declined/revoked invoices. |
7. Query Invoice POST
Purpose of Use: The POST /esf/query-invoice-request endpoint searches ESF invoices by criteria (direction, date range, status, type) and returns them converted into the platform's own InvoiceDTO shape, ready for display.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/query-invoice-request |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/query-invoice-request' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"criteria": {
"direction": "INBOUND",
"dateFrom": "2026-09-01T00:00:00+06:00",
"dateTo": "2026-09-30T23:59:59+06:00",
"invoiceStatusList": ["DELIVERED", "CREATED"],
"invoiceType": "ORDINARY_INVOICE",
"asc": false,
"pageNum": 0
}
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| criteria.direction | String (Enum) | No | INBOUND (default) or OUTBOUND. |
| criteria.dateFrom / criteria.dateTo | DateTime | No | Date range filter. |
| criteria.invoiceStatusList | Array<String> | No | Filter by one or more InvoiceStatus values. |
| criteria.invoiceType | String (Enum) | No | ORDINARY_INVOICE, FIXED_INVOICE, or ADDITIONAL_INVOICE. |
| criteria.asc | Boolean | No | Sort direction. |
| criteria.pageNum | Integer | No | Page number. |
InvoiceType Values
| Value | Description |
|---|---|
| ORDINARY_INVOICE | Standard ESF invoice |
| FIXED_INVOICE | Corrective ESF invoice (A4) |
| ADDITIONAL_INVOICE | Supplementary ESF invoice (A5) |
Responses
200 - Successful Response
[
{
"id": "22116203282",
"companyId": "79499e36-6d45-4c7d-bc52-...",
"invoiceGuid": "a1b2c3d4-...",
"slipDate": "2026-09-16",
"issueDate": "2026-09-16",
"slipNr": "00900023888",
"taxNr": "123456789012",
"clientName": "Supplier LLP",
"status": "DELIVERED",
"invoiceType": "ORDINARY_INVOICE",
"invoiceNo": "00900023888",
"quantity": 10,
"price": 1500.00,
"grossTotal": 16800.00,
"netTotal": 15000.00,
"totalVat": 1800.00,
"payableAmount": 16800.00,
"currencyCode": "KZT",
"itemList": []
}
]
| Field | Type | Description |
|---|---|---|
| id | String | ESF numeric invoice ID, as a string. |
| companyId | UUID | Shared platform company identifier. |
| invoiceGuid | String | ESF's own GUID for the invoice, when present. |
| slipDate / issueDate / deliveryDocDate | String (Date) | Document dates. |
| slipNr / invoiceNo / deliveryDocNum | String | Document numbers. |
| taxNr | String | Counterparty TIN/BIN. |
| clientName | String | Counterparty name. |
| status | String (Enum) | See the InvoiceStatus table above. |
| invoiceType | String (Enum) | See the InvoiceType table above. |
| invoiceObjectXml / xmlData | String | Raw XML, when requested/available. |
| htmlView / pdfView | String | Rendered views, when available. |
| quantity | Integer | Line item count or quantity summary. |
| price / grossTotal / netTotal / totalDiscount / totalVat / payableAmount / vat | BigDecimal | Monetary fields. Never null — default to zero when absent. |
| currencyCode | String | ISO 4217 currency code. |
| currencyRate | Double | Exchange rate applied, when the currency is not KZT. |
| itemList | Array<Object> | Line items, when available. |
8. Query Invoice by ID POST
Purpose of Use: The POST /esf/query-invoice-by-id-request endpoint retrieves the full ESF XML body and metadata for a specific set of invoices by their numeric ESF ID — the direct counterpart of Query Updates for a known ID rather than a date range.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/query-invoice-by-id-request |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/query-invoice-by-id-request' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282] }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| idList | Array<Long> | Yes | ESF numeric invoice IDs to retrieve. |
Responses
200 - Successful Response
{
"lastBlock": true,
"currPage": 0,
"rsCount": 1,
"invoiceInfoList": {
"invoiceInfo": [ { "invoiceId": 22116203282, "invoiceBody": "<BASE64_ESF_V2_XML>", "invoiceStatus": "DELIVERED" } ]
}
}
| Field | Type | Description |
|---|---|---|
| lastBlock | Boolean | Whether this is the final page of results. |
| currPage | Integer | Current page number. |
| rsCount | Integer | Total result count. |
| invoiceInfoList.invoiceInfo | Array<Object> | Same InvoiceInfo shape as in Query Updates. |
9. Query Invoice by Key POST
Purpose of Use: The POST /esf/query-invoice-by-key-request endpoint is identical to Query Invoice by ID, but looks invoices up by their business key (invoice number + date) instead of the ESF numeric ID — useful when the ESF ID was never recorded locally.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/query-invoice-by-key-request |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/query-invoice-by-key-request' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"invoiceKeyList": [ { "num": "00900023888", "date": "2026-09-16" } ],
"direction": "OUTBOUND"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| invoiceKeyList | Array<Object> | Yes | Keys to look up. |
| invoiceKeyList[].num | String | Yes | Invoice number. |
| invoiceKeyList[].date | String | Yes | Invoice date. |
| direction | String (Enum) | Yes | INBOUND or OUTBOUND — the number/date pair is only unique within one direction. |
Responses
Same response shape as Query Invoice by ID.
10. Query Invoice Summary by ID POST
Purpose of Use: The POST /esf/query-invoice-summary-by-id-request endpoint returns just the summary (status, dates, registration number) for a batch of invoice IDs — without the full XML body — for a lighter-weight status check than Query Invoice by ID.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/query-invoice-summary-by-id-request |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/query-invoice-summary-by-id-request' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282] }'
Request Parameters
Same as Query Invoice by ID: idList (Array<Long>, required).
Responses
200 - Successful Response
{
"invoiceSummaryList": {
"invoiceSummary": [
{
"invoiceId": 22116203282,
"date": "2026-09-16",
"invoiceStatus": "DELIVERED",
"num": "00900023888",
"cancelReason": null,
"registrationNumber": "KZ...",
"lastUpdateDate": "2026-09-16T07:26:00"
}
]
}
}
| Field | Type | Description |
|---|---|---|
| invoiceSummaryList.invoiceSummary | Array<Object> | One summary per requested ID. |
| [].invoiceId | Long | ESF numeric invoice ID. |
| [].date / [].num | String | Invoice date/number. |
| [].invoiceStatus | String (Enum) | See the InvoiceStatus table above. |
| [].cancelReason | String | null | Populated for canceled/declined/revoked invoices. |
| [].registrationNumber | String | Government registration number. |
| [].lastUpdateDate | DateTime | Last status change timestamp. |
11. Query Invoice Summary by Key POST
Purpose of Use: The POST /esf/query-invoice-summary-by-key-request endpoint is the summary-only counterpart of Query Invoice by Key.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/query-invoice-summary-by-key-request |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/query-invoice-summary-by-key-request' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"invoiceKeyList": [ { "num": "00900023888", "date": "2026-09-16" } ],
"direction": "OUTBOUND"
}'
Request Parameters
Same as Query Invoice by Key: invoiceKeyList and direction.
Responses
Same response shape as Query Invoice Summary by ID.
12. Query Invoice History by ID POST
Purpose of Use: The POST /esf/query-invoice-history-by-id-request endpoint returns the full status change history (audit trail) of an ESF invoice — who changed it, to what status, and when.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/query-invoice-history-by-id-request |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/query-invoice-history-by-id-request' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282] }'
Request Parameters
Same as Query Invoice by ID: idList.
Responses
200 - Successful Response
{
"resultList": {
"esfHistory": [
{
"invoiceId": 22116203282,
"status": "DELIVERED",
"dateTime": "2026-09-16T07:26:00",
"userId": "123456789012",
"tin": "123456789012",
"statusDescription": "Invoice delivered to recipient",
"clientType": "SUPPLIER"
}
]
}
}
| Field | Type | Description |
|---|---|---|
| resultList.esfHistory | Array<Object> | Chronological list of status changes. |
| [].invoiceId | Long | ESF numeric invoice ID. |
| [].status | String (Enum) | See the InvoiceStatus table above. |
| [].dateTime | DateTime | When the change occurred. |
| [].userId / [].tin | String | Who made the change. |
| [].statusDescription | String | Human-readable description of the change. |
| [].clientType | String (Enum) | Whether the change was made by the SUPPLIER or the CUSTOMER side. |
13. Query Invoice Error by ID POST
Purpose of Use: The POST /esf/query-invoice-error-by-id-request endpoint returns the validation errors recorded against a FAILED invoice — the detail that Upload Invoice List's declinedSet gives inline, retrievable later by ID.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/query-invoice-error-by-id-request |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/query-invoice-error-by-id-request' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282] }'
Request Parameters
Same as Query Invoice by ID: idList.
Responses
200 - Successful Response
{
"invoiceErrorList": {
"invoiceError": [
{
"invoiceId": 22116203282,
"errors": { "error": [ { "property": "seller.tin", "errorCode": "REQUIRED", "text": "Seller TIN is required" } ] }
}
]
}
}
| Field | Type | Description |
|---|---|---|
| invoiceErrorList.invoiceError | Array<Object> | One entry per requested invoice. |
| [].invoiceId | Long | ESF numeric invoice ID. |
| [].errors.error[].property | String | The XML field that failed validation. |
| [].errors.error[].errorCode | String | ESF error code. |
| [].errors.error[].text | String | Human-readable error description. |
14. Approve Invoice by ID POST
Purpose of Use: The POST /esf/approve-by-id endpoint is the recipient's acceptance action — it moves one or more invoices to the CREATED/delivered-and-accepted state.
Shared result shape: This endpoint and the five that follow (Confirm, Confirm Revoke, Decline, Revoke, Unrevoke) all return the same TryChangeStatusResponse envelope, shown once here.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/approve-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/approve-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282] }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| idList | Array<Long> | Yes | ESF numeric invoice IDs to approve. |
Responses
200 - Successful Response
{
"resultList": {
"changeStatusResult": [
{
"invoiceSummary": { "invoiceId": 22116203282, "invoiceStatus": "CREATED", "num": "00900023888", "date": "2026-09-16" },
"isChanged": true,
"errorCode": null,
"errorText": null
}
]
}
}
| Field | Type | Description |
|---|---|---|
| resultList.changeStatusResult | Array<Object> | One result per requested ID, in request order — a partial success for some IDs never discards the others. |
| [].invoiceSummary | Object | The invoice's resulting summary — same shape as Query Invoice Summary by ID's items. |
| [].isChanged | Boolean | Whether the status actually changed as a result of this call. |
| [].errorCode / [].errorText | String | null | Populated when isChanged is false because the transition was not allowed from the invoice's current status. |
15. Confirm Invoice by ID POST
Purpose of Use: The POST /esf/confirm-by-id endpoint confirms one or more invoices.
⚠️ Different response envelope: Unlike its five siblings, this endpoint's native ESF operation returns an InvoiceSummaryResponse (a flat list of summaries) rather than TryChangeStatusResponse — there is no per-item isChanged/errorCode.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/confirm-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/confirm-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282] }'
Request Parameters
Same as Approve Invoice by ID: idList.
Responses
200 - Successful Response
{
"invoiceSummaryList": {
"invoiceSummary": [
{ "invoiceId": 22116203282, "invoiceStatus": "WAITING_CUSTOMER_CONFIRMATION", "num": "00900023888", "date": "2026-09-16" }
]
}
}
Same InvoiceSummary field shape as Query Invoice Summary by ID.
16. Confirm Revoke Invoice by ID POST
Purpose of Use: The POST /esf/confirm-revoke-by-id endpoint is the recipient's confirmation of a supplier's revoke request — completing the two-sided revoke flow once the supplier has called Revoke Invoice by ID.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/confirm-revoke-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/confirm-revoke-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282] }'
Request Parameters
Same as Approve Invoice by ID: idList.
Responses
Same TryChangeStatusResponse envelope as Approve Invoice by ID — resulting status REVOKED.
17. Decline Invoice by ID POST
Purpose of Use: The POST /esf/decline-by-id endpoint is the recipient's rejection action, with a required reason per invoice.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/decline-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/decline-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idWithReasonList": [ { "id": 22116203282, "reason": "Incorrect quantity" } ] }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| idWithReasonList | Array<Object> | Yes | One or more invoices to decline. |
| idWithReasonList[].id | Long | Yes | ESF numeric invoice ID. |
| idWithReasonList[].reason | String | Yes | Reason for declining. |
Responses
Same TryChangeStatusResponse envelope as Approve Invoice by ID — resulting status DECLINED.
18. Revoke Invoice by ID POST
Purpose of Use: The POST /esf/revoke-invoice-by-id endpoint is the supplier's revoke request — it starts the two-sided revoke flow (status moves to WAITING_CUSTOMER_REVOKE_CONFIRMATION) that the recipient completes via Confirm Revoke Invoice by ID.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/revoke-invoice-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/revoke-invoice-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idWithReasonList": [ { "id": 22116203282, "reason": "Incorrect quantity" } ] }'
Request Parameters
Same as Decline Invoice by ID: idWithReasonList.
Responses
Same TryChangeStatusResponse envelope as Approve Invoice by ID — resulting status WAITING_CUSTOMER_REVOKE_CONFIRMATION.
19. Unrevoke Invoice by ID POST
Purpose of Use: The POST /esf/unrevoke-invoice-by-id endpoint cancels a revoke request that has not yet been confirmed by the recipient, restoring the invoice's prior status.
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/unrevoke-invoice-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/unrevoke-invoice-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idWithReasonList": [ { "id": 22116203282, "reason": "Reconsidered — invoice is valid" } ] }'
Request Parameters
Same as Decline Invoice by ID: idWithReasonList.
Responses
Same TryChangeStatusResponse envelope as Approve Invoice by ID.
20. Delete Invoice by ID POST
Purpose of Use: The POST /esf/delete-by-id endpoint deletes one or more ESF invoices that have not progressed past a deletable status (e.g. a DRAFT or FAILED invoice).
Endpoint Information
| Property | Value |
|---|---|
| URL | /esf/delete-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/esf/delete-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [22116203282] }'
Request Parameters
Same as Approve Invoice by ID: idList.
Responses
200 - Successful Response
{
"resultList": {
"changeStatusResult": [
{ "invoiceId": 22116203282, "isDeleted": true }
]
}
}
| Field | Type | Description |
|---|---|---|
| resultList.changeStatusResult | Array<Object> | One result per requested ID. |
| [].invoiceId | Long | ESF numeric invoice ID. |
| [].isDeleted | Boolean | false when the invoice's current status does not allow deletion. |
About this section: The endpoints below (/snt prefix) are Kazakhstan's native SNT (waybill) integration layer — the ESF system's companion service for electronic waybills (накладные), mirroring the /esf section's pattern one-to-one. The same rules apply: authentication is via a company-bound API key (no compId parameter), authority ADMIN or ERP_MANAGEMENT_API_KEY_GENERATE is required, and IDs are the SNT service's own numeric sntId.
SNT
Электронная счет-фактура товаротранспортная накладная (ЭСФ ТТН) / electronic waybill (SNT) — Kazakhstan's electronic waybill exchange with the KGD, tracking the physical movement of goods alongside the ESF invoice. All endpoints below share the /snt prefix and the same authorization as ESF.
1. Upload SNT POST
Purpose of Use: The POST /snt/upload-snt endpoint submits one or more signed SNT (waybill) XML documents to the government service.
⚠️ Note: Like ESF's Upload Invoice List, every document in sntUploadInfoList is validated and submitted independently — one rejection does not affect the others.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/upload-snt |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/upload-snt' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"sntUploadInfoList": [
{
"sntBody": "<BASE64_ENCODED_SNT_V1_XML>",
"version": "SntV1",
"signature": "<BASE64_SNT_SIGNATURE>",
"signatureType": "COMPANY"
}
]
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| sntUploadInfoList | Array<Object> | Yes | One or more waybills to submit. |
| sntUploadInfoList[].sntBody | String (Base64) | Yes | The SNT XML body, Base64-encoded. |
| sntUploadInfoList[].version | String (Enum) | No | SntV1 (default, and currently the only version). |
| sntUploadInfoList[].signature | String | Yes | E-signature over the SNT body. |
| sntUploadInfoList[].signatureType | String (Enum) | Yes | COMPANY or OPERATOR. |
Responses
200 - Successful Response
{
"acceptedList": {
"sntUploadResult": [ { "sntId": 9887654321, "number": "SNT-00012345", "date": "2026-09-16" } ]
},
"declinedList": {
"sntUploadResult": [
{ "number": "SNT-00012346", "date": "2026-09-16", "errorList": { "error": [ { "property": "recipient.tin", "errorCode": "REQUIRED", "text": "Recipient TIN is required" } ] } }
]
}
}
| Field | Type | Description |
|---|---|---|
| acceptedList.sntUploadResult / declinedList.sntUploadResult | Array<Object> | One entry per submitted document, split by outcome. |
| [].sntId | Long | SNT's own numeric ID. Present only in acceptedList. Use this as idList on the query/action endpoints below. |
| [].number / [].date | String | Waybill number/date, echoed from the XML. |
| [].errorList.error[] | Array<Object> | Validation errors, when declined — same property/errorCode/text shape as ESF's errors. |
2. Get Unread Waybills POST
Purpose of Use: The POST /snt/unread-waybills endpoint is the SNT equivalent of ESF's Query Updates — the polling primitive for new/changed waybills since a given cursor.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/unread-waybills |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/unread-waybills' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"direction": "INBOUND",
"lastEventDate": "2026-09-16T07:00:00",
"lastSntId": 9887654300,
"limit": 50
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| direction | String (Enum) | No | INBOUND or OUTBOUND. |
| lastEventDate | DateTime | No | Resume point. Omit to start from the beginning. |
| lastSntId | Long | No | Tie-breaker for lastEventDate. |
| limit | Integer | No | Page size. |
Responses
200 - Successful Response
{
"lastEventDate": "2026-09-16T07:30:00",
"lastSntId": 9887654321,
"lastBlock": true,
"sntInfoList": {
"sntInfo": [
{
"sntId": 9887654321,
"inputDate": "2026-09-16T07:25:50",
"lastUpdateDate": "2026-09-16T07:26:00",
"registrationNumber": "KZ...",
"version": "SntV1",
"status": "DELIVERED"
}
]
}
}
| Field | Type | Description |
|---|---|---|
| lastEventDate / lastSntId | — | Pass both back on the next call to resume from here. |
| lastBlock | Boolean | false means more pages are ready now — call again immediately. |
| sntInfoList.sntInfo | Array<Object> | The batch of updated waybills — see SntInfo fields below. |
SntInfo Fields
| Field | Type | Description |
|---|---|---|
| sntId | Long | SNT numeric ID. |
| inputDate / lastUpdateDate / dateForFixed | DateTime | Lifecycle timestamps. |
| registrationNumber | String | Government registration number, once assigned. |
| version | String (Enum) | SntV1. |
| status | String (Enum) | See the SntStatus table below. |
| documentInfo | Object | Shipment document details (sender/recipient, goods, transport). |
| acceptanceGoodsInfo | Object | null | Goods acceptance details, once the recipient has acted. |
| ogdMarksInfo | Object | null | Customs/tax authority marks, when applicable. |
| cancelReason | String | null | Populated for canceled/revoked/declined waybills. |
| primarySntId | Long | null | The original waybill this one corrects/supersedes, when applicable. |
SntStatus Values
| Value | Description |
|---|---|
| DRAFT | Draft |
| NOT_VIEWED | Not yet viewed by the recipient |
| DELIVERED | Delivered |
| CREATED | Created |
| IMPORTED | Imported from a legacy system |
| FAILED | Failed |
| CONFIRMED | Confirmed by recipient |
| DECLINED | Declined by recipient |
| CONFIRMED_BY_OGD | Confirmed by tax authority inspector |
| DECLINED_BY_OGD | Declined by tax authority inspector |
| CANCELED | Canceled |
| REVOKED | Revoked |
| SEND_TO_ISGO | Forwarded to ISGO (goods tracking) |
3. Query SNT by ID POST
Purpose of Use: The POST /snt/query-snt-by-id endpoint retrieves the full details for a specific set of waybills by their numeric SNT ID.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/query-snt-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/query-snt-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [9887654321] }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| idList | Array<Long> | Yes | SNT numeric IDs to retrieve. |
Responses
200 - Successful Response
{
"lastBlock": true,
"currPage": 0,
"rsCount": 1,
"sntInfoList": { "sntInfo": [ { "sntId": 9887654321, "status": "DELIVERED" } ] }
}
Same SntInfo shape as Get Unread Waybills, paginated the same way as ESF's Query Invoice by ID.
4. Query by Regnum POST
Purpose of Use: The POST /snt/query-by-regnum endpoint resolves one or more government registration numbers to the platform's internal SNT numeric IDs — needed because the registration number is only assigned after submission and is not known ahead of time.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/query-by-regnum |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/query-by-regnum' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "regnumList": ["KZ20260916000012345"] }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| regnumList | Array<String> | Yes | Government registration numbers to resolve. |
Responses
200 - Successful Response
{
"regnumIdMap": {
"entry": [ { "key": "KZ20260916000012345", "value": 9887654321 } ]
}
}
| Field | Type | Description |
|---|---|---|
| regnumIdMap.entry | Array<Object> | One map entry per requested registration number. |
| [].key | String | The registration number, echoed. |
| [].value | Long | The resolved SNT numeric ID — use this on the other query/action endpoints. |
5. Query Status by Regnum POST
Purpose of Use: The POST /snt/query-status-by-regnum endpoint returns an extended status summary directly by registration number, skipping the two-step resolve-then-query of Query by Regnum + Query SNT by ID — and additionally surfaces any linked FNO matching information (goods declaration cross-checks).
Status credit: Each new status this endpoint reads from KGD is charged as described in Status credit (Introduction); this endpoint and Query SNT Status by ID charge one SNT once for the same status. Without credit the call answers HTTP 400 LIFECYCLE_CREDIT_EXHAUSTED and KGD is not asked.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/query-status-by-regnum |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/query-status-by-regnum' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "regnumList": ["KZ20260916000012345"] }'
Request Parameters
Same as Query by Regnum: regnumList.
Responses
200 - Successful Response
{
"sntExtendedSummaryList": {
"sntExtendedSummary": [
{
"summary": { "sntId": 9887654321, "registrationNumber": "KZ20260916000012345", "status": "DELIVERED", "senderTin": "123456789012", "recipientTin": "987654321098", "matchingNotification": false },
"fnoMatchingInfos": null
}
]
}
}
| Field | Type | Description |
|---|---|---|
| sntExtendedSummaryList.sntExtendedSummary | Array<Object> | One entry per resolved registration number. |
| [].summary | Object (SntSummary) | See fields below. |
| [].fnoMatchingInfos | Object | null | Linked goods-declaration matching records, when any exist. |
SntSummary Fields
| Field | Type | Description |
|---|---|---|
| sntId | Long | SNT numeric ID. |
| inputDate / lastUpdateDate | DateTime | Lifecycle timestamps. |
| registrationNumber | String | Government registration number. |
| version | String | SNT schema version. |
| status | String (Enum) | See the SntStatus table in Get Unread Waybills. |
| cancelReason | String | null | Populated for canceled/declined/revoked waybills. |
| senderTin / recipientTin | String | Parties' TIN/BIN. |
| matchingNotification | Boolean | Whether an FNO matching discrepancy notification exists for this waybill. |
6. Query View SNT POST
Purpose of Use: The POST /snt/query-view-snt endpoint marks the specified waybills as viewed by the recipient and returns their change-status result — used when a recipient opens a waybill in the UI, moving it out of NOT_VIEWED.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/query-view-snt |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/query-view-snt' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [9887654321] }'
Request Parameters
Same as Query SNT by ID: idList.
Responses
200 - Successful Response
{
"resultList": {
"changeStatusResult": [
{ "sntSummary": { "sntId": 9887654321, "status": "DELIVERED" }, "isChanged": true, "canceledInvoiceRegNumbers": null, "errors": null, "notifications": null }
]
}
}
| Field | Type | Description |
|---|---|---|
| resultList.changeStatusResult | Array<Object> | One result per requested ID. |
| [].sntSummary | Object | Same SntSummary shape as Query Status by Regnum. |
| [].isChanged | Boolean | Whether the view was newly recorded. |
| [].canceledInvoiceRegNumbers | Array<String> | null | ESF invoice registration numbers canceled as a side effect, when applicable. |
| [].errors | Array<Object> | null | Populated when the action could not be applied. |
| [].notifications | Array<Object> | null | Any notifications raised as a result of this action. |
Shared envelope: This changeStatusResult shape is also used by Change Status (below).
7. Query SNT History by ID POST
Purpose of Use: The POST /snt/query-snt-history-by-id endpoint returns the full status change history (audit trail) of a waybill — the SNT equivalent of ESF's Query Invoice History by ID.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/query-snt-history-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/query-snt-history-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [9887654321] }'
Request Parameters
Same as Query SNT by ID: idList.
Responses
200 - Successful Response
{
"resultList": {
"sntHistory": [
{ "sntId": 9887654321, "date": "2026-09-16T07:26:00", "tin": "123456789012", "clientType": "SUPPLIER", "userId": "...", "status": "DELIVERED", "statusDescription": "Waybill delivered", "action": "SEND" }
]
}
}
| Field | Type | Description |
|---|---|---|
| resultList.sntHistory | Array<Object> | Chronological list of status changes. |
| [].sntId | Long | SNT numeric ID. |
| [].date | DateTime | When the change occurred. |
| [].tin / [].userId | String | Who made the change. |
| [].clientType | String (Enum) | SUPPLIER or CUSTOMER. |
| [].status | String (Enum) | See the SntStatus table in Get Unread Waybills. |
| [].statusDescription | String | Human-readable description. |
| [].action | String (Enum) | The action type that produced this history entry. |
8. Query SNT Error by ID POST
Purpose of Use: The POST /snt/query-snt-error-by-id endpoint returns the validation errors recorded against a FAILED waybill.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/query-snt-error-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/query-snt-error-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [9887654321] }'
Request Parameters
Same as Query SNT by ID: idList.
Responses
200 - Successful Response
{
"sntErrorList": {
"sntError": [
{ "sntId": 9887654321, "errors": { "error": [ { "property": "recipient.tin", "errorCode": "REQUIRED", "text": "Recipient TIN is required" } ] } }
]
}
}
Same property/errorCode/text error shape as ESF's Query Invoice Error by ID.
9. Change Status POST
Purpose of Use: The POST /snt/change-status endpoint is the general-purpose waybill lifecycle action — confirm, decline, cancel, or otherwise act on one or more waybills, with the action itself carried inside each waybill's signed action body rather than as a separate parameter.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/change-status |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/change-status' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"sntActionInfoList": [
{
"sntId": 9887654321,
"sntActionBody": "<BASE64_ENCODED_ACTION_XML>",
"sntVersion": "SntV1",
"signatureType": "COMPANY"
}
]
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| sntActionInfoList | Array<Object> | Yes | One or more actions to apply. |
| sntActionInfoList[].sntId | Long | Yes | The waybill to act on. |
| sntActionInfoList[].sntActionBody | String (Base64) | Yes | The signed action XML (confirm/decline/cancel), Base64-encoded. |
| sntActionInfoList[].sntVersion | String (Enum) | No | SntV1 (default). |
| sntActionInfoList[].signatureType | String (Enum) | No | COMPANY or OPERATOR. |
Responses
Same changeStatusResult envelope as Query View SNT above.
10. Delete Waybill by ID POST
Purpose of Use: The POST /snt/delete-by-id endpoint deletes one or more waybills that have not progressed past a deletable status.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/delete-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/delete-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "sntActionInfoList": [ { "sntId": 9887654321 } ] }'
Request Parameters
Same shape as Change Status (sntActionInfoList); the SNT service only requires sntId per entry for a delete.
Responses
200 - Successful Response
{
"resultList": {
"changeStatusResult": [
{ "sntId": 9887654321, "isDeleted": true, "errorCode": null }
]
}
}
| Field | Type | Description |
|---|---|---|
| resultList.changeStatusResult | Array<Object> | One result per requested waybill. |
| [].sntId | Long | SNT numeric ID. |
| [].isDeleted | Boolean | false when the waybill's current status does not allow deletion. |
| [].errorCode | String | null | Populated when deletion was refused. |
11. Query SNT Status by ID POST
Purpose of Use: The POST /snt/query-snt-status-by-id endpoint returns KGD's current status summary (without the XML body) for one or more SNTs by their numeric IDs.
Status credit: Each new status this endpoint reads from KGD is charged as described in Status credit (Introduction); this endpoint and Query Status by Regnum charge one SNT once for the same status. Without credit the call answers HTTP 400 LIFECYCLE_CREDIT_EXHAUSTED and KGD is not asked.
Endpoint Information
| Property | Value |
|---|---|
| URL | /snt/query-snt-status-by-id |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) + company-bound API key |
Example Request
curl --location 'https://api-stage.docnova.ai/snt/query-snt-status-by-id' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "idList": [9887654321] }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| idList | Array<Long> | Yes | SNT numeric IDs (KGD's SNT id, e.g. kgdSntId from Section 8). |
Responses
200 - Successful Response
{
"sntSummaryList": {
"sntSummary": [
{ "sntId": 9887654321, "registrationNumber": "KZ20260916000012345", "status": "DELIVERED", "lastUpdateDate": "2026-09-16T08:00:00" }
]
}
}
| Field | Type | Description |
|---|---|---|
| sntSummaryList.sntSummary | Array<Object (SntSummary)> | One summary per SNT; same SntSummary fields as Query Status by Regnum. |
VWH
Виртуальный склад (ВС) / Virtual Warehouse (VWH) — Kazakhstan's real-time inventory tracking integration with the KGD, covering reference data (Dict), warehouse registration (Store), stock levels (Balance), inventory movements (UForm) and goods-receipt requests (ZVT).
Internal variants only: The endpoints below are the Internal controller variants — Authorization is a company-restricted R-Auth JWT obtained via API-key login, same as ESF/SNT: the company is resolved from the token's restrictedCompanyId, so no explicit companyId is sent in most requests. Base path: /kz/vwh/internal. (The platform also exposes External VWH controllers, with normal JWTs and an explicit companyId parameter, which are out of scope for this guide.)
⚠️ POST/PUT bodies carry Base64-encoded KGD XML: Unlike ESF/SNT/AVR (which carry individually-typed JSON fields), most VWH write endpoints accept a single Base64-encoded KGD XML document as their only body field (storeXml, uFormXml, zvtXml). The XML must not include an <?xml?> declaration or an outer wrapper element — only the inner document body, and its element order must follow the KGD XSD exactly.
Dict (Reference Data)
1. Get Measure Units GET
Purpose of Use: The GET /kz/vwh/internal/dict/measure-units endpoint returns KGD's measurement unit dictionary, optionally filtered to entries updated after a given date.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/dict/measure-units |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/dict/measure-units?lastUpdateDate=2026-01-01T00%3A00%3A00' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| lastUpdateDate | DateTime | No | Returns only entries updated after this date. Omit to retrieve the full dictionary. |
Responses
200 - Successful Response
[
{
"code": "166",
"codeMkei": "166",
"codeOkei": "166",
"codeTis": "166",
"nameRu": "Килограмм",
"nameKz": "Килограмм",
"lastUpdateDate": "2017-10-01T00:00:00+05:00"
}
]
| Field | Type | Description |
|---|---|---|
| code | String | KGD measure unit code — used as measureUnitCode elsewhere in VWH. |
| codeMkei / codeOkei / codeTis | String | Equivalent codes in other Kazakhstan classification systems. |
| nameRu / nameKz | String | Unit name in Russian and Kazakh. |
| lastUpdateDate | DateTime | When this entry was last updated in KGD's dictionary. |
2. Get GSVS Code Updates GET
Purpose of Use: The GET /kz/vwh/internal/dict/gsvs endpoint polls KGD's product classification (GSVS) dictionary for changes, paginated by an incrementing changeId.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/dict/gsvs |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/dict/gsvs?lastChangeId=0&blockSize=100' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| lastChangeId | Long | No | Resume point from a previous call. Default: 0. |
| blockSize | Integer | No | Page size. Default: 100. KGD accepts at most 200. |
Responses
200 - Successful Response
[
{
"changeDate": "2026-01-01T00:00:00",
"changeId": "100045",
"operation": "ADD",
"code": "10.61.11.01",
"gsvsCode": "10.61.11.01",
"description": null,
"nameRu": "Мука пшеничная",
"nameKz": "Бидай ұны",
"gsvsTypeCode": "GOODS",
"id": "100045",
"fixedId": "100045",
"fixedParentId": null,
"isDeleted": false,
"isCanSelect": true,
"isTwofoldPurpose": false,
"endDate": null
}
]
| Field | Type | Description |
|---|---|---|
| changeId | String | Pass as lastChangeId on the next call to resume from here. |
| operation | String | The dictionary change type, e.g. ADD/UPDATE. |
| code / gsvsCode | String | The GSVS classification code — used as gsvsCode on UForm product lines and AVR work lines. Only entries with isCanSelect = true can be used. |
| nameRu / nameKz | String | The entry's official Russian and Kazakh names. An AVR work line (work/name) must carry one of them letter for letter, or KGD fails the AVR with AWP_WORK_NAME_INCORRECT. |
| description | String | null | Always null: KGD does not send it. Use nameRu / nameKz. |
| gsvsTypeCode | String | Classification type. |
| id / fixedId / fixedParentId | String | Internal and fixed hierarchy identifiers. |
| isDeleted / isCanSelect / isTwofoldPurpose | Boolean | Entry flags. |
| endDate | DateTime | When the entry stopped being valid, if applicable. |
3. Evict Dict Cache POST
Purpose of Use: The POST /kz/vwh/internal/dict/cache/evict endpoint clears the server-side cache backing the Dict endpoints above, forcing the next call to re-fetch from KGD.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/dict/cache/evict |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location --request POST 'https://api-stage.docnova.ai/kz/vwh/internal/dict/cache/evict' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
None.
Responses
204 - No Content
No response body.
Store
4. List Stores GET
Purpose of Use: The GET /kz/vwh/internal/store endpoint lists all warehouses/points of sale registered for the calling company.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/store |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/store' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
None — the company is taken from the JWT.
Responses
200 - Successful Response
[
{
"id": 16011,
"tin": "123456789012",
"storeName": "Almaty Warehouse",
"storeTypeCode": "STORE_HOUSE",
"status": "VALID",
"address": "Almaty, Kabanbay Batyr Ave 15",
"responsiblePersonIin": "123456789012",
"isDefault": false,
"isJointStore": false,
"isPostingGoods": true,
"isInherited": false
}
]
| Field | Type | Description |
|---|---|---|
| id | Long | Store's numeric ID — used as storeId elsewhere in VWH. |
| tin | String | Owning company's TIN/BIN. |
| storeName | String | Store display name. |
| storeTypeCode | String (Enum) | POINT_OF_SALE or STORE_HOUSE. |
| status | String (Enum) | VALID (active) or INVALID (closed). |
| address | String | Physical address. |
| responsiblePersonIin | String | IIN of the person responsible for the store. |
| isDefault | Boolean | Whether this is the company's default store. |
| isJointStore | Boolean | Whether the store is shared/joint. |
| isPostingGoods | Boolean | Whether goods receipts can be posted to this store. |
| isInherited | Boolean | Whether the store was inherited rather than created directly. |
5. Create Store POST
Purpose of Use: The POST /kz/vwh/internal/store endpoint registers a new warehouse/point of sale with KGD from a Base64-encoded KGD Store XML document.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/store |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
⚠️ Field names differ from the REST response: The KGD Store XML uses name and type — not storeName/storeTypeCode as returned by List Stores. No <?xml?> declaration or wrapper element.
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/store' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "storeXml": "<BASE64_ENCODED_STORE_XML>" }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| storeXml | String (Base64) | Yes | The KGD Store XML body, Base64-encoded (schema below). |
KGD Store XML Schema
| XML Element | Required | Type | Description |
|---|---|---|---|
| name | Yes | String | Store name. |
| type | Yes | eStoreType | POINT_OF_SALE or STORE_HOUSE. |
| responsiblePersonIin | Yes | String | IIN of the responsible person. |
| isDefault | Yes | Boolean | Whether this is the default store. |
| isInherited | Yes | Boolean | Whether the store is inherited. |
| isJointStore | Yes | Boolean | Whether the store is a joint store. |
| isPostingGoods | Yes | Boolean | Whether goods receipts can be posted. |
| address | No | String | Store address. |
<name>Almaty Warehouse</name>
<address>Almaty, Kabanbay Batyr Ave 15</address>
<type>STORE_HOUSE</type>
<responsiblePersonIin>123456789012</responsiblePersonIin>
<isInherited>false</isInherited>
<isDefault>false</isDefault>
<isJointStore>false</isJointStore>
<isPostingGoods>true</isPostingGoods>
Responses
200 OK — a KzVwhStoreResponse, same field shape as List Stores above.
6. Update Store PUT
Purpose of Use: The PUT /kz/vwh/internal/store/{storeId} endpoint updates an existing store's details via a Base64-encoded KGD Store XML document, using the same schema as Create Store.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/store/{storeId} |
| Method | PUT |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location --request PUT 'https://api-stage.docnova.ai/kz/vwh/internal/store/16852' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "storeXml": "<BASE64_ENCODED_STORE_XML>" }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| storeId (path) | Long | Yes | The store to update. |
| storeXml | String (Base64) | Yes | Same KGD Store XML schema as Create Store. |
Responses
204 - No Content
No response body.
7. Close Store DELETE
Purpose of Use: The DELETE /kz/vwh/internal/store/{storeId} endpoint closes a store. KGD does not physically delete it — its status is set to INVALID.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/store/{storeId} |
| Method | DELETE |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location --request DELETE 'https://api-stage.docnova.ai/kz/vwh/internal/store/16852' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| storeId (path) | Long | Yes | The store to close. |
Responses
204 - No Content
No response body.
Balance
8. Query Current Balance GET
Purpose of Use: The GET /kz/vwh/internal/balance endpoint returns the current stock level per product/store, optionally filtered and paginated.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/balance |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/balance?storeId=16011&tnvedCode=1006201500' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| lastBalanceId | Long | No | Pagination cursor from a previous call. |
| storeId | Long | No | Filter to a specific store. |
| tnvedCode | String | No | Filter by EAEU TN VED commodity code. |
Responses
200 - Successful Response
[
{
"balanceId": 152687,
"tin": "123456789012",
"taxpayerStoreId": 16011,
"projectCode": null,
"name": "Wheat flour, 50kg bag",
"kpvedCode": "10.61.11.01",
"tnvedCode": "1006201500",
"gtinCode": null,
"productId": 1029296,
"measureUnitCode": "166",
"unitPrice": 10.00,
"quantity": 9.000000,
"reserveQuantity": 0.000000,
"spiritPercent": null,
"receiptDocNumber": "123456789012/O/290426/38972333",
"productNumberInReceiptDoc": "1",
"manufactureOrImportDocNumber": null,
"productNumberInImportDoc": null,
"productNameInImportDoc": null,
"physicalLabel": null,
"pinCode": null,
"dutyType": "NOT_INSTALLED",
"countryCode": "KZ",
"originCode": "4",
"originType": "MANUFACTURE",
"markingCode": null,
"confiscated": false,
"canExport": true,
"createDate": "2026-04-29T10:49:32+05:00"
}
]
| Field | Type | Description |
|---|---|---|
| balanceId | Long | Pass as lastBalanceId to page through results. |
| taxpayerStoreId | Long | The store this balance belongs to. |
| kpvedCode / tnvedCode | String | Product classification codes. |
| productId | Long | VWH's internal product identifier. |
| measureUnitCode | String | See Get Measure Units above. |
| unitPrice / quantity / reserveQuantity | Decimal | Price and on-hand/reserved quantities. |
| receiptDocNumber / productNumberInReceiptDoc | String | The goods-receipt document and line this stock came from. |
| dutyType | String (Enum) | CCT, WTO, EAEU or NOT_INSTALLED. |
| countryCode / originCode / originType | String | Country of origin details. |
| canExport / confiscated | Boolean | Export eligibility and confiscation flags. |
| createDate | DateTime | When this balance record was created. |
9. Query Product IDs GET
Purpose of Use: The GET /kz/vwh/internal/balance/product-ids endpoint resolves VWH's internal productId for one or more goods-receipt document registration numbers.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/balance/product-ids |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/balance/product-ids?registrationNumbers=123456789012%2FO%2F290426%2F38972333' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| registrationNumbers | Array<String> | No | One or more goods-receipt document registration numbers (repeat the query parameter for multiple values). |
Responses
200 - Successful Response
[
{
"balanceId": 152687,
"productId": 1029296,
"receiptDocNumber": "123456789012/O/290426/38972333",
"productNumberInReceiptDoc": "1",
"taxpayerStoreId": 16011,
"kpvedCode": "10.61.11.01",
"tnvedCode": "1006201500",
"measureUnitCode": "166",
"unitPrice": 10.00,
"quantity": 9.000000,
"manufactureOrImportDocNumber": null,
"productNumberInImportDoc": null,
"productNameInImportDoc": null,
"canExport": true,
"confiscated": false,
"markingCode": null,
"dutyType": "NOT_INSTALLED",
"countryCode": "KZ",
"originCode": "4",
"originType": "MANUFACTURE",
"createDate": "2026-04-29T10:49:32+05:00"
}
]
Same field meanings as Query Current Balance above, keyed to the requested registrationNumbers.
10. Query Reserved Products GET
Purpose of Use: The GET /kz/vwh/internal/balance/reserved endpoint returns stock reservation events (quantity held against an in-progress movement/sale) since a given date.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/balance/reserved |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/balance/reserved?lastEventDate=01.01.2026%2000%3A00%3A00' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| lastEventDate | String | Yes | Reservation events after this date. Format: dd.MM.yyyy HH:mm:ss (URL-encoded). |
| lastBalanceId | Long | No | Pagination cursor from a previous call. |
Responses
200 - Successful Response
[
{
"balanceId": 152700,
"tin": "123456789012",
"taxpayerStoreId": 16011,
"productId": 1029296,
"quantity": 2.000000,
"measureUnitCode": "166",
"movementDoc": "MOV-2026-00045",
"productNumberInMovementDoc": "1",
"reserveQuantity": 2.000000,
"createDate": "2026-05-01T09:00:00+05:00"
}
]
| Field | Type | Description |
|---|---|---|
| balanceId | Long | Pass as lastBalanceId to page through results. |
| movementDoc / productNumberInMovementDoc | String | The document/line that created the reservation. |
| quantity / reserveQuantity | Decimal | Quantity involved and quantity reserved. |
| createDate | DateTime | When the reservation event occurred. |
UForm
UForm (Universal Form): The single mechanism for reporting all inventory movements to KGD — initial balance declaration, manufacturing output, inter-store transfer, and write-off — distinguished by uFormType. Submission endpoints each accept a Base64-encoded KGD UForm XML; its type is implied by the endpoint called (not re-declared in the body).
11. Submit Balance UForm POST
Purpose of Use: The POST /kz/vwh/internal/uform/balance endpoint declares a company's opening stock balance to KGD — typically the first UForm submitted for a new store/product.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/balance |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/balance' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "uFormXml": "<BASE64_ENCODED_UFORM_XML>" }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| uFormXml | String (Base64) | Yes | The KGD UForm XML body, Base64-encoded (schema below). |
KGD UForm XML Schema (strict element order)
| Order | XML Element | Required | Type | Description |
|---|---|---|---|---|
| 1 | date | Yes | String | Form date — format dd.MM.yyyy. |
| 2 | number | Yes | String | Sender's own accounting number for this form. |
| 3 | recipient | No | Object | Recipient info (required for MOVEMENT). |
| 4 | sender | No | Object | Sender info. |
| 5 | totalSum | No | Decimal | Total amount. |
| 6 | type | Yes | euFormType | Implied by the endpoint; must match it. |
| 7 | comment | No | String | Free-text comment. |
| 8 | products | No | Array<Object> | Product lines (schema below). |
| 9 | writeOffReason | No | uFormWriteOffType | Required for WRITE_OFF. |
sender / recipient element order: name → storeId → storeName → tin (required).
UForm Product Line Schema (strict element order)
| Order | XML Element | Required | Type | Description |
|---|---|---|---|---|
| 1 | gsvsCode | Yes | String | GSVS classification code. |
| 2 | measureUnitCode | Yes | String | See Get Measure Units. |
| 3 | price | No | Decimal | Unit price. |
| 4 | quantity | Yes | Decimal | Quantity. |
| 5 | sum | No | Decimal | Line total. |
| 6 | canExport | No | Boolean | Export eligibility. |
| 7 | dutyTypeCode | No | eCustomsDutyType | CCT, WTO, EAEU, NOT_INSTALLED. |
| 8 | originCode | No | String | Origin code. |
| 9 | manufactureOrImportCountry | No | String | Country of manufacture/import. |
| 10 | manufactureOrImportDocNumber | No | String | Manufacture/import document number. |
| 13 | name | Yes | String | Product name. |
| 18 | tnvedCode | No | String | EAEU TN VED code. |
<?xml version="1.0" encoding="UTF-8"?><v1:uForm xmlns:v1="namespace.v1" xmlns:abs="namespace.abstractUForm"><date>14.05.2026</date><number>BAL-001</number><sender><storeId>16011</storeId><tin>123456789012</tin></sender><totalSum>1500.00</totalSum><type>BALANCE</type><products><product><gsvsCode>10.61.11.01</gsvsCode><measureUnitCode>166</measureUnitCode><price>1500.00</price><quantity>1.000000</quantity><sum>1500.00</sum><canExport>true</canExport><dutyTypeCode>NOT_INSTALLED</dutyTypeCode><originCode>4</originCode><manufactureOrImportCountry>KAZ</manufactureOrImportCountry><name>Test Product</name></product></products></v1:uForm>
⚠️ Not Base64 above: The XML is shown decoded for readability; the actual uFormXml field value must be this document Base64-encoded, with no <?xml?> declaration stripped at the application layer (KGD accepts it either way, but encode exactly what you intend to submit).
Responses
200 - Successful Response
{
"id": "6f1b2a3c-4d5e-6f70-8a9b-0c1d2e3f4a5b",
"uFormNumber": "BAL-001",
"uFormType": "BALANCE",
"status": "CREATED",
"kgdRegistrationNumber": "KZ...",
"senderTin": "123456789012",
"recipientTin": null,
"senderStoreId": 16011,
"recipientStoreId": null,
"errorMessage": null,
"createdTime": "2026-05-12T10:00:00",
"updatedTime": "2026-05-12T10:00:00"
}
| Field | Type | Description |
|---|---|---|
| id | UUID | This UForm's identifier in the platform — use it as id on the endpoints below. |
| uFormNumber | String | Echoed from number in the XML. |
| uFormType | String (Enum) | See the KzVwhUFormType table below. |
| status | String (Enum) | See the KzVwhUFormStatus table below. |
| kgdRegistrationNumber | String | Government registration number, once assigned. |
| senderTin / recipientTin | String | Parties involved; recipientTin is populated only for MOVEMENT. |
| senderStoreId / recipientStoreId | Long | Stores involved. |
| errorMessage | String | Populated when status is FAILED. |
| createdTime / updatedTime | DateTime | Lifecycle timestamps. |
KzVwhUFormType Values
| Value | Description |
|---|---|
| BALANCE | Opening stock declaration — this endpoint. |
| MANUFACTURE | Manufacturing output — Submit Manufacture UForm. |
| MOVEMENT | Inter-store transfer — Submit Movement UForm. |
| WRITE_OFF | Write-off/disposal — Submit Write-Off UForm. |
| BALANCE_CORRECTION | Balance correction (not exposed by a dedicated submission endpoint below). |
| DETAILING | Detailing (not exposed by a dedicated submission endpoint below). |
KzVwhUFormStatus Values
| Value | Description |
|---|---|
| DRAFT | Draft, not yet submitted to KGD. |
| CREATED | Accepted and created. |
| IN_PROCESSING | Being processed by KGD. |
| WAIT_INSTOCK | Waiting on stock availability. |
| WAIT_DOCUMENT | Waiting on a related document. |
| PROCESSED | Fully processed. |
| CANCELED | Canceled. |
| FAILED | Rejected/failed — see errorMessage. |
12. Submit Manufacture UForm POST
Purpose of Use: The POST /kz/vwh/internal/uform/manufacture endpoint reports manufacturing output into stock, using the same UForm XML schema as Submit Balance UForm with type set to MANUFACTURE.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/manufacture |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/manufacture' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "uFormXml": "<BASE64_ENCODED_UFORM_XML_TYPE_MANUFACTURE>" }'
Request Parameters
Same as Submit Balance UForm (uFormXml), with type set to MANUFACTURE in the decoded XML.
Responses
200 OK — a KzVwhUFormResponse, same field shape as Submit Balance UForm above.
13. Submit Movement UForm POST
Purpose of Use: The POST /kz/vwh/internal/uform/movement endpoint reports a transfer of stock between two stores. Unlike the other UForm types, both sender and recipient must be populated in the XML.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/movement |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/movement' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "uFormXml": "<BASE64_ENCODED_UFORM_XML_TYPE_MOVEMENT_WITH_SENDER_AND_RECIPIENT>" }'
Request Parameters
Same as Submit Balance UForm (uFormXml), with type set to MOVEMENT and both sender and recipient populated in the decoded XML.
Responses
200 OK — a KzVwhUFormResponse; both senderStoreId/senderTin and recipientStoreId/recipientTin are populated.
14. Submit Write-Off UForm POST
Purpose of Use: The POST /kz/vwh/internal/uform/writeoff endpoint reports stock removed from inventory (damage, loss, recycling, etc.), requiring writeOffReason in the XML.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/writeoff |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/writeoff' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "uFormXml": "<BASE64_ENCODED_UFORM_XML_TYPE_WRITE_OFF>" }'
Request Parameters
Same as Submit Balance UForm (uFormXml), with type set to WRITE_OFF and writeOffReason populated in the decoded XML.
KzVwhWriteOffReason Values
| Value | Description |
|---|---|
| MANUFACTURE | Used in manufacturing. |
| DAMAGE | Damaged. |
| RECYCLING | Recycled. |
| RECLAMATION | Reclamation. |
| LOSS | Lost. |
| IS_NOT_VSTORE | This TN VED code is not within VWH's scope. |
| CONVERSION | Written off for raw-material conversion. |
| OTHER | Other reason. |
Responses
200 OK — a KzVwhUFormResponse, same field shape as Submit Balance UForm above.
15. List UForms GET
Purpose of Use: The GET /kz/vwh/internal/uform endpoint lists all UForms submitted by the calling company.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
None — the company is taken from the JWT.
Responses
200 OK — Array<KzVwhUFormResponse>, same field shape as Submit Balance UForm's response.
16. Search UForms POST
Purpose of Use: The POST /kz/vwh/internal/uform/search endpoint filters UForms by date range, type, status and store, returning a paginated result.
⚠️ Exception to the Internal pattern: This endpoint requires an explicit companyId in the request body rather than resolving it from the JWT. If the JWT is company-restricted, companyId must match the token's company.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/search |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) — companyId must match the token's restricted company, if any |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/search?page=0&size=20' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{
"companyId": "60ccd1a7-5348-47b2-9ef6-000000000000",
"createdTime": { "from": "2026-05-01T00:00:00", "to": "2026-05-31T23:59:59" },
"types": ["BALANCE", "MOVEMENT"],
"statuses": ["PROCESSED"],
"senderStoreId": 16011,
"recipientStoreId": null
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | UUID | Yes | The company to search within. |
| createdTime | Object | No | from/to date-time range filter. |
| types | Array<Enum> | No | Filter by one or more KzVwhUFormType values. |
| statuses | Array<Enum> | No | Filter by one or more KzVwhUFormStatus values. |
| senderStoreId / recipientStoreId | Long | No | Filter by sender/recipient store. |
Standard Spring page/size/sort query parameters are also accepted for pagination.
Responses
200 - Successful Response
{
"content": [
{ "id": "6f1b2a3c-4d5e-6f70-8a9b-0c1d2e3f4a5b", "uFormNumber": "BAL-001", "uFormType": "BALANCE", "status": "PROCESSED", "senderTin": "123456789012", "senderStoreId": 16011, "createdTime": "2026-05-12T10:00:00" }
],
"totalElements": 1,
"totalPages": 1,
"number": 0,
"size": 20
}
A standard Spring Data Page envelope; content items share the KzVwhUFormResponse shape from Submit Balance UForm's response.
17. Get UForm by ID GET
Purpose of Use: The GET /kz/vwh/internal/uform/{id} endpoint retrieves a single UForm by its platform UUID.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/{id} |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/6f1b2a3c-4d5e-6f70-8a9b-0c1d2e3f4a5b' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The UForm's platform identifier. |
Responses
200 OK — a KzVwhUFormResponse, same field shape as Submit Balance UForm's response.
18. Get UForm Details GET
Purpose of Use: The GET /kz/vwh/internal/uform/details/{id} endpoint returns the raw KGD-side detail record for a UForm, including its signature and full body — useful when the summary from Get UForm by ID is not enough.
Status credit: Each new status this endpoint reads from KGD is charged as described in Status credit (Introduction). Without credit the call answers HTTP 400 LIFECYCLE_CREDIT_EXHAUSTED and KGD is not asked.
⚠️ Exception to the Internal pattern: This endpoint also requires an explicit companyId query parameter rather than resolving it from the JWT, like Search UForms above.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/details/{id} |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (JWT token) — companyId must match the token's restricted company, if any |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/details/6f1b2a3c-4d5e-6f70-8a9b-0c1d2e3f4a5b?companyId=60ccd1a7-5348-47b2-9ef6-000000000000' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The UForm's platform identifier. |
| companyId (query) | UUID | Yes | The owning company. |
Responses
200 - Successful Response
{
"uFormId": 90045,
"uFormBody": "<BASE64_UFORM_XML>",
"status": "PROCESSED",
"registrationNumber": "KZ...",
"inputDate": "2026-05-12T10:00:00",
"lastUpdateDate": "2026-05-12T10:05:00",
"signatureValid": true,
"cancelReason": null,
"version": "UFormV1",
"signature": "<BASE64_SIGNATURE>",
"signatureType": "COMPANY",
"creatorLogin": "api-user-1"
}
| Field | Type | Description |
|---|---|---|
| uFormId | Long | KGD's own numeric UForm identifier (distinct from the platform's id UUID). |
| uFormBody | String (Base64) | The full UForm XML as held by KGD. |
| status | String (Enum) | See the KzVwhUFormStatus table above. |
| registrationNumber | String | Government registration number. |
| inputDate / lastUpdateDate | String | Lifecycle timestamps as returned by KGD. |
| signatureValid | Boolean | Whether the e-signature validated successfully. |
| cancelReason | String | Populated when canceled. |
| version / signature / signatureType | String | Document version, e-signature and signature type. |
| creatorLogin | String | The KGD user/login that created the record. |
19. Cancel UForm POST
Purpose of Use: The POST /kz/vwh/internal/uform/{id}/cancel endpoint cancels a UForm, with a mandatory reason.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/{id}/cancel |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location --request POST 'https://api-stage.docnova.ai/kz/vwh/internal/uform/6f1b2a3c-4d5e-6f70-8a9b-0c1d2e3f4a5b/cancel?cancelReason=Entered%20in%20error' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The UForm to cancel. |
| cancelReason (query) | String | Yes | Reason for cancellation. |
Responses
200 OK — a KzVwhUFormResponse with status set to CANCELED.
20. Cancel UForm DELETE
Purpose of Use: The DELETE /kz/vwh/internal/uform/{id} endpoint is an alternate way to cancel a UForm, with the cancellation reason optional.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/{id} |
| Method | DELETE |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location --request DELETE 'https://api-stage.docnova.ai/kz/vwh/internal/uform/6f1b2a3c-4d5e-6f70-8a9b-0c1d2e3f4a5b' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The UForm to cancel. |
| cancelReason (query) | String | No | Reason for cancellation. Default: empty. |
Responses
200 OK — a KzVwhUFormResponse with status set to CANCELED.
21. Get UForm Live Status GET
Purpose of Use: The GET /kz/vwh/internal/uform/{id}/status endpoint queries KGD directly for the UForm's current status, bypassing the platform's locally cached value.
Status credit: Each new status this endpoint reads from KGD is charged as described in Status credit (Introduction). Without credit the call answers HTTP 400 LIFECYCLE_CREDIT_EXHAUSTED and KGD is not asked.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/{id}/status |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/6f1b2a3c-4d5e-6f70-8a9b-0c1d2e3f4a5b/status' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The UForm to check. |
Responses
200 OK — a KzVwhUFormResponse, same field shape as Submit Balance UForm's response, refreshed from KGD.
22. Get UForm Live Errors GET
Purpose of Use: The GET /kz/vwh/internal/uform/{id}/errors endpoint queries KGD directly for any validation errors recorded against the UForm.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/{id}/errors |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/6f1b2a3c-4d5e-6f70-8a9b-0c1d2e3f4a5b/errors' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The UForm to check. |
Responses
200 OK — a KzVwhUFormResponse; errorMessage carries KGD's validation error text when present.
23. Get UForm Updates GET
Purpose of Use: The GET /kz/vwh/internal/uform/updates endpoint is the polling primitive for UForm changes — given the last event date already processed, it returns raw field data for UForms updated since then.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/uform/updates |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/uform/updates?lastEventDate=2026-05-01T00%3A00%3A00' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| lastEventDate | DateTime | Yes | Returns updates after this date (ISO format). Mandatory — KGD's SOAP layer rejects the call without it. |
Responses
200 - Successful Response
{
"lastEventDate": "2026-05-01T12:00:00",
"lastBlock": true,
"uFormInfoList": [
{ "uFormId": "90045", "status": "PROCESSED", "registrationNumber": "KZ..." }
]
}
| Field | Type | Description |
|---|---|---|
| lastEventDate | String | Pass back as-is on the next call to continue from here. |
| lastBlock | Boolean | true when this page is the last available page. |
| uFormInfoList | Array<Object> | Raw key/value field map per updated UForm, passed through directly from KGD rather than mapped to a fixed shape — field names may vary by update type. |
ZVT
24. Create ZVT POST
Purpose of Use: The POST /kz/vwh/internal/zvt endpoint submits a goods-receipt request (ZVT — "Заявка на возврат товара"/goods-receipt notification) to KGD from a Base64-encoded XML document.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/zvt |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/zvt' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}' \
--data '{ "zvtXml": "<BASE64_ENCODED_ZVT_XML>" }'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| zvtXml | String (Base64) | Yes | The ZVT XML document, Base64-encoded. The decoded content (not the raw string) is what gets forwarded to KGD. |
Responses
200 - Successful Response
{
"registrationNumber": "KZ...",
"status": "CREATED",
"errorMessage": null,
"errorCode": null,
"body": "<BASE64_ZVT_XML>",
"inputDate": "2026-05-14T09:00:00"
}
| Field | Type | Description |
|---|---|---|
| registrationNumber | String | Government registration number, once assigned — use this as regnum on the endpoints below. |
| status | String | KGD-reported status. |
| errorMessage / errorCode | String | Populated when the submission failed validation. |
| body | String (Base64) | The submitted XML, echoed back. |
| inputDate | String | When the request was received. |
25. Query ZVT by Period GET
Purpose of Use: The GET /kz/vwh/internal/zvt endpoint lists ZVT documents submitted within a date range.
⚠️ KGD limits the period to 1 day: periodFrom/periodTo cannot span more than 24 hours — longer ranges are rejected by KGD.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/zvt |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/zvt?periodFrom=14.05.2026%2000%3A00%3A00&periodTo=14.05.2026%2023%3A59%3A59' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| periodFrom | String | Yes | Period start. Format: dd.MM.yyyy HH:mm:ss (URL-encoded). |
| periodTo | String | Yes | Period end. Same format. Max 1 day after periodFrom. |
| lastId | Long | No | Pagination cursor from a previous call. |
Responses
200 OK — Array<KzVwhZvtDocumentResponse>, same field shape as Create ZVT's response.
26. Get ZVT by Registration Number GET
Purpose of Use: The GET /kz/vwh/internal/zvt/{regnum} endpoint retrieves a single ZVT document by its government registration number.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/zvt/{regnum} |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/zvt/KZ20260514000123' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| regnum (path) | String | Yes | ZVT government registration number. |
Responses
200 OK — a KzVwhZvtDocumentResponse, same field shape as Create ZVT's response.
27. Query ZVT by Registration Numbers GET
Purpose of Use: The GET /kz/vwh/internal/zvt/regnum endpoint retrieves multiple ZVT documents in one call by their registration numbers.
Status credit: Each new status this endpoint reads from KGD is charged as described in Status credit (Introduction). Without credit the call answers HTTP 400 LIFECYCLE_CREDIT_EXHAUSTED and KGD is not asked.
Endpoint Information
| Property | Value |
|---|---|
| URL | /kz/vwh/internal/zvt/regnum |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | R-Auth header (company-restricted JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/kz/vwh/internal/zvt/regnum?regnums=KZ20260514000123®nums=KZ20260514000124' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| regnums | Array<String> | Yes | One or more ZVT registration numbers (repeat the query parameter for multiple values). |
Responses
200 OK — Array<KzVwhZvtDocumentResponse>, same field shape as Create ZVT's response.
AVR
Акт выполненных работ (АВР) — the Act of Completed Works/Services, a Kazakhstan e-document exchanged with the KGD (State Revenue Committee) alongside ESF and SNT. It is coded internally as AWP.
Docnova signs and tracks AVRs on your behalf (recommended for ERPs). The ERP sends the AVR data as a JSON object or a Base64-encoded XML document; Docnova checks it, signs it with the company's KGD certificate (uploaded in the Docnova portal), uploads it to KGD, stores the record and follows its status at KGD every minute.
Prerequisite: Before using any AVR endpoint, the company's KGD certificate must be uploaded in the Docnova portal (Settings → KGD Certificate). Docnova uses this certificate to sign documents on the ERP's behalf.
1. Create AVR
There are two ways to submit an AVR:
- JSON format (send-document-async-json) — send AVR data as a structured JSON object; Docnova builds the XML internally. Recommended for most ERP integrations.
- Base64 XML format (send-document-async) — send a fully-formed AwpV1 XML file encoded as Base64. Use when your ERP already builds KGD-compatible XML.
Both endpoints are asynchronous: they return a trackingId immediately and process the document in the background. Use GET /invoice/document-status/{trackingId} to retrieve the result. The documentId in the completed response is Docnova's AVR record ID — use it for Get AVR, history, PDF, and all action endpoints.
1a. Create AVR — JSON Format POST
Purpose of Use: The POST /invoice/send-document-async-json endpoint accepts AVR data as a plain JSON object, signs it with the company's KGD certificate, uploads it to KGD, and tracks its status. The ERP does not need to build XML.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/send-document-async-json |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token obtained with the company's API key |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async-json' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"compId": "{COMPANY_ID}",
"waybillType": "KZ_AWP",
"senderSignerName": "Генеральный директор",
"awp": {
"companyId": "{COMPANY_ID}",
"number": "AVR-2026-0001",
"avrDate": "06.11.2026",
"performedDate": "05.11.2026",
"senderTin": "123456789012",
"senderName": "TOO Performer",
"senderAddress": "Almaty",
"senderRegistrationType": "ENTERPRISE",
"recipientTin": "987654321098",
"recipientName": "TOO Customer",
"recipientAddress": "Almaty",
"recipientRegistrationType": "ENTERPRISE",
"currencyCode": "KZT",
"totalNdsAmount": 0,
"totalSumWithTax": 100000,
"totalSumWithoutTax": 100000,
"totalTurnoverSize": 100000,
"works": [
{
"name": "Услуги по аренде машин и оборудования для строительства промышленного и гражданского",
"gsvsCode": "77.32.10.01",
"quantity": 1,
"measureUnitCode": "5114",
"unitPriceWithoutTax": 100000,
"sumWithoutTax": 100000,
"sumWithTax": 100000,
"turnoverSize": 100000
}
]
}
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| compId | String (UUID) | Yes | Docnova UUID of the sending company |
| waybillType | String (Enum) | Yes | Fixed value: KZ_AWP |
| senderSignerName | String | Yes | Position of the person signing on the sender side, e.g. Генеральный директор. Required by KGD on every upload. |
| awp | Object | Yes | AVR content — fields below |
| awp.companyId | String (UUID) | Yes | Same as compId |
| awp.number | String | Yes | AVR number, e.g. AVR-2026-0001 |
| awp.avrDate | String (dd.MM.yyyy) | Yes | AVR date — must match the KGD server's current date |
| awp.performedDate | String (dd.MM.yyyy) | No | Date the work was actually performed |
| awp.senderTin | String | Yes | Sender company TIN — must match the company's TIN on the token |
| awp.senderName | String | Yes | Sender company name |
| awp.senderAddress | String | Yes | Sender company address |
| awp.senderRegistrationType | String (Enum) | Yes | Sender participant type at KGD — must match the company's registered type (usually ENTERPRISE). See Registration Type Values below. |
| awp.recipientTin | String | Yes | Recipient company TIN |
| awp.recipientName | String | Yes | Recipient company name |
| awp.recipientAddress | String | Yes | Recipient company address |
| awp.recipientRegistrationType | String (Enum) | Conditional | Required when recipient is a resident (nonResident = false); must be omitted when non-resident |
| awp.currencyCode | String | Yes | Currency code, e.g. KZT |
| awp.totalNdsAmount | Decimal | Yes | Total VAT amount; send 0 if the company is not a VAT payer |
| awp.totalSumWithTax | Decimal | Yes | Total amount including VAT |
| awp.totalSumWithoutTax | Decimal | Yes | Total amount excluding VAT |
| awp.totalTurnoverSize | Decimal | Yes | Total taxable turnover (equals totalSumWithoutTax for non-VAT payers) |
| awp.works | Array<Object> | Yes | Work line items — at least one entry required |
| awp.works[].name | String | Yes | Official GSVS dictionary name for the service (Russian or Kazakh) — must match the code's dictionary name exactly |
| awp.works[].gsvsCode | String | Yes | GSVS service code, e.g. 77.32.10.01 |
| awp.works[].quantity | Number | Yes | Quantity |
| awp.works[].measureUnitCode | String | Yes | Unit of measure code |
| awp.works[].unitPriceWithoutTax | Decimal | Yes | Unit price excluding VAT |
| awp.works[].sumWithoutTax | Decimal | Yes | Line total excluding VAT |
| awp.works[].sumWithTax | Decimal | Yes | Line total including VAT |
| awp.works[].turnoverSize | Decimal | Yes | Line taxable turnover |
Responses
202 - Request Accepted
{
"trackingId": "f9e16331-85e3-40ae-bb94-eabd4ed12759",
"status": "PENDING",
"message": "Document processing request submitted successfully"
}
Poll GET /invoice/document-status/{trackingId} until status is COMPLETED or FAILED.
{
"trackingId": "f9e16331-85e3-40ae-bb94-eabd4ed12759",
"status": "COMPLETED",
"invoiceNumber": "AVR-2026-0001",
"documentId": "0f86baee-bd04-4682-887e-7e20a576c7ae",
"additionalData": {
"kgdAwpId": "946365",
"awpStatus": "CREATED"
}
}
| Field | Type | Description |
|---|---|---|
| trackingId | UUID | Use to poll GET /invoice/document-status/{trackingId} |
| status | String (Enum) | PENDING → COMPLETED or FAILED |
| documentId | UUID | Docnova's AVR record ID — use for Get AVR, history, PDF and all action endpoints |
| additionalData.kgdAwpId | String | KGD's numeric AVR ID |
| additionalData.awpStatus | String | KGD status at the time of completion — see AVR Status Values below |
1b. Create AVR — Base64 XML Format POST
Purpose of Use: The POST /invoice/send-document-async endpoint accepts a fully-formed AwpV1 XML document encoded as Base64. Use this variant when your ERP already generates KGD-compatible AVR XML. Docnova signs, uploads and tracks the document; the ERP receives a trackingId and polls for the result the same way as the JSON endpoint.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/send-document-async |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"compId": "{COMPANY_ID}",
"waybillType": "KZ_AWP",
"base64Document": "{BASE64_ENCODED_AWP_XML}",
"senderSignerName": "Генеральный директор"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| compId | String (UUID) | Yes | Docnova UUID of the sending company |
| waybillType | String (Enum) | Yes | Fixed value: KZ_AWP |
| base64Document | String (Base64) | Yes | AwpV1 AVR XML, UTF-8, Base64-encoded. Single-line and line-wrapped Base64 (CRLF or LF) are both accepted. |
| senderSignerName | String | Yes | Position of the person signing on the sender side. Required by KGD on every upload. |
Responses
Same structure as 1a — trackingId on 202, then poll GET /invoice/document-status/{trackingId}.
Registration Type Values
Used in senderRegistrationType and recipientRegistrationType.
| Value | Description |
|---|---|
| ENTERPRISE | Legal entity (ТОО, АО, etc.) |
| ENTREPRENEUR | Individual entrepreneur (ИП) |
| INDIVIDUAL | Private individual |
| LAWYER | Lawyer |
| NOTARY | Notary |
| MEDIATOR | Mediator |
| BAILIFF | Bailiff |
| JOINT_ACTIVITY_PARTICIPANT | Joint activity participant |
| SHARING_AGREEMENT_PARTICIPANT | Production sharing agreement participant |
The sender's registrationType must match the company's registered participant type at KGD. For most companies this is ENTERPRISE. The recipient's registrationType is required when nonResident = false and must be omitted when nonResident = true.
AVR Status Values
| Status | Description | Final? |
|---|---|---|
| DRAFT | Upload in progress, or KGD's answer was not received. The AVR may already be registered at KGD — do not resend it; contact Docnova. | No |
| CREATED | KGD received and registered the upload. Transitions to NOT_VIEWED within seconds once KGD processes it. | No |
| NOT_VIEWED | Accepted by KGD; the customer has not opened the document yet. | No |
| DELIVERED | The customer has viewed the document. | No |
| CONFIRMED | The customer confirmed the AVR. | Yes |
| DECLINED | The customer declined the AVR. | Yes |
| REVOKED | The sender cancelled the AVR before it was confirmed. | Yes |
| IN_TERMINATING | Termination initiated by one party; waiting for the other party to confirm. | No |
| TERMINATED | Both parties agreed to terminate a previously confirmed AVR. | Yes |
| CANCELED | Cancelled by KGD. | Yes |
| IMPORTED | Brought into KGD outside the API (legacy). | Yes |
| FAILED | KGD refused the upload or failed the AVR after acceptance. The errorMessage field contains KGD's errors. The AVR number is free to reuse — correct and resend under the same number. | Yes |
Status Transition Flow
┌──────────────────────────────────────┐
▼ │ REVOKE
DRAFT ──► CREATED ──► NOT_VIEWED ──► DELIVERED ──┤
│ CONFIRM ──► CONFIRMED ──► IN_TERMINATING ──► TERMINATED
│
└──► DECLINED
| From | Action | To |
|---|---|---|
| (upload) | Docnova uploads to KGD | DRAFT → CREATED → NOT_VIEWED |
| NOT_VIEWED | Customer opens the document | DELIVERED |
| DELIVERED | Customer confirms | CONFIRMED |
| DELIVERED | Customer declines | DECLINED |
| CREATED / NOT_VIEWED / DELIVERED | Sender revokes | REVOKED |
| CONFIRMED | Either party initiates termination | IN_TERMINATING |
| IN_TERMINATING | The other party confirms termination | TERMINATED |
2. Get AVR GET
Purpose of Use: The GET /api/awp/{id} endpoint returns Docnova's AVR record with its current status. Docnova reads AVR statuses from KGD every minute, so this call does not call KGD itself. Suggested polling interval: every 5–15 minutes, only for AVRs that are not in a final status.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}?companyId={companyId} |
| Method | GET |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — user token or company API key |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{AVR_ID}?companyId={COMPANY_ID}' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Accept: application/json'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The documentId returned by Create AVR (the trackingId completion response) |
| companyId (query) | UUID | Yes | The company the AVR belongs to. With a company-scoped token it must match the token's company; otherwise COMPANY_SCOPE_MISMATCH |
Responses
200 - Successful Response
{
"id": "0f86baee-bd04-4682-887e-7e20a576c7ae",
"internalId": "AWP-2026-00205",
"status": "TERMINATED",
"role": "PERFORMER",
"kgdAwpId": "946365",
"kgdReference": "AVR-2026-006",
"kgdRegistrationNumber": "AKT-160840016422-261105-00441662",
"ourTin": "160840016422",
"counterpartyTin": "940240000498",
"counterpartyName": "Invivo",
"contractNumber": null,
"contractDate": null,
"avrDate": "05.11.2026",
"performedDate": "04.11.2026",
"currencyCode": "KZT",
"totalSumWithTax": 1000,
"totalNdsAmount": 0,
"corrected": false,
"parentAwpId": null,
"errorMessage": null,
"senderRegistrationType": "ENTERPRISE",
"recipientRegistrationType": "ENTERPRISE",
"recipientNonResident": false,
"esfConvertible": false,
"linkedEsf": null,
"createdTime": "2026-11-04T19:27:45",
"updatedTime": "2026-11-05T09:02:21",
"workItems": [
{
"id": "415c80fd-4dec-4c9e-91c3-d8394d2e07c4",
"name": "Услуги по аренде машин и оборудования для строительства промышленного и гражданского",
"gsvsCode": "77.32.10.01",
"quantity": 1,
"unitPrice": 1000,
"ndsRate": null,
"sumWithTax": 1000,
"sumWithoutTax": 1000,
"turnoverSize": 1000,
"ndsAmount": null,
"measureUnitCode": "5114",
"additionalInfo": null
}
]
}
| Field | Type | Description |
|---|---|---|
| id | UUID | Docnova's AVR record ID. Use this for history, PDF and all action endpoints. |
| internalId | String | Docnova's human-readable record number, e.g. AWP-2026-00205. |
| status | String (Enum) | Current AVR status — see AVR Status Values. |
| role | String (Enum) | PERFORMER for an AVR the company sent; CUSTOMER for one it received. |
| kgdAwpId | String | KGD's numeric AVR ID. |
| kgdReference | String | The AVR number as echoed by KGD. |
| kgdRegistrationNumber | String | KGD's official registration number, format AKT-<TIN>-<yyMMdd>-<sequence>. May be null immediately after upload. |
| ourTin | String | The calling company's TIN. |
| counterpartyTin | String | The other party's TIN. |
| counterpartyName | String | The other party's name. |
| contractNumber / contractDate | String | Contract details from the AVR XML, if provided. |
| avrDate | String (dd.MM.yyyy) | AVR issue date. |
| performedDate | String | Date the work was performed. |
| currencyCode | String | Currency code, e.g. KZT. |
| totalSumWithTax | Decimal | Total amount including VAT. |
| totalNdsAmount | Decimal | Total VAT amount; 0 for non-VAT payers. |
| corrected | Boolean | true if this is a correction AVR. |
| parentAwpId | UUID | Docnova ID of the original AVR this corrects; null for primary AVRs. |
| errorMessage | String | KGD error details when status is FAILED. |
| senderRegistrationType | String (Enum) | Sender's participant type — see Registration Type Values. |
| recipientRegistrationType | String (Enum) | Recipient's participant type. |
| recipientNonResident | Boolean | true if the recipient is a non-resident. |
| esfConvertible | Boolean | Whether an ESF can be created from this AVR in the Docnova portal. |
| linkedEsf | Object | ESF linked to this AVR, if one was created. |
| createdTime | DateTime | When the Docnova record was created. |
| updatedTime | DateTime | When the record was last updated. |
| workItems | Array<Object> | Work line items — see fields below. |
| statusSyncPaused | Boolean | Present only when status polling is paused due to insufficient credit. |
| statusSyncPausedReason | String | Reason for the pause, when statusSyncPaused is true. |
workItems fields:
| Field | Type | Description |
|---|---|---|
| id | UUID | Docnova's internal ID for this work line. |
| name | String | Official GSVS dictionary name for the service. |
| gsvsCode | String | GSVS service classification code, e.g. 77.32.10.01. |
| quantity | Number | Quantity (6 decimal places). |
| unitPrice | Decimal | Unit price excluding VAT. |
| ndsRate | Integer | VAT rate (%); null for non-VAT payers. |
| ndsAmount | Decimal | VAT amount for this line; null for non-VAT payers. |
| sumWithTax | Decimal | Line total including VAT. |
| sumWithoutTax | Decimal | Line total excluding VAT. |
| turnoverSize | Decimal | Taxable turnover for this line. |
| measureUnitCode | String | Unit of measure code, e.g. 5114 (services). |
| additionalInfo | String | Optional additional information. |
404 - Error Response
| HTTP | Code | Description |
|---|---|---|
| 404 | AWP_NOT_FOUND | No AVR with this ID in the company. |
3. Get AVR History GET
Purpose of Use: The GET /api/awp/{id}/history endpoint returns every status change Docnova has recorded for the AVR, ordered from newest to oldest. Use it to audit the full lifecycle of a document — when each transition happened, what triggered it, and what comment was left.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}/history?companyId={companyId} |
| Method | GET |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — user token or company API key |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{AVR_ID}/history?companyId={COMPANY_ID}' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Accept: application/json'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The documentId returned by Create AVR |
| companyId (query) | UUID | Yes | The company the AVR belongs to |
Responses
200 - Successful Response
[
{
"id": "f4e52678-47de-438c-b3db-0493cad08fd8",
"oldStatus": "IN_TERMINATING",
"newStatus": "TERMINATED",
"source": "SCHEDULER",
"comment": null,
"createdTime": "2026-11-05T09:02:21"
},
{
"id": "0d8f111e-07d6-46fc-9aaf-97a0f5a4c7c0",
"oldStatus": "CONFIRMED",
"newStatus": "IN_TERMINATING",
"source": "USER",
"comment": "Termination request",
"createdTime": "2026-11-05T08:40:35"
}
]
| Field | Type | Description |
|---|---|---|
| id | UUID | Docnova's internal ID for this history entry. |
| oldStatus | String (Enum) | AVR status before the change — see AVR Status Values. |
| newStatus | String (Enum) | AVR status after the change. |
| source | String (Enum) | What triggered the transition — see Source Values below. |
| comment | String | The reason provided with the action. null for SCHEDULER-triggered transitions. |
| createdTime | DateTime | When the status change was recorded. |
Source Values:
| Value | Description |
|---|---|
| SCHEDULER | Status read from KGD by Docnova's periodic polling (every minute). No user action involved. |
| USER | Action taken through the Docnova portal or API (confirm, decline, revoke, initiate/confirm termination). |
| SAP | Triggered by the Create AVR endpoint submission. |
404 - Error Response
| HTTP | Code | Description |
|---|---|---|
| 404 | AWP_NOT_FOUND | No AVR with this ID in the company. |
4. Download AVR PDF GET
Purpose of Use: The GET /api/awp/{id}/pdf endpoint returns the AVR as a downloadable PDF file, laid out as the official Kazakh form Р-1 (Annex 50 to MinFin Order No. 562 of 20 December 2012). The PDF is generated entirely from Docnova's stored data — no KGD call is made and no credit is charged.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}/pdf?companyId={companyId} |
| Method | GET |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — user token or company API key |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{AVR_ID}/pdf?companyId={COMPANY_ID}' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Accept: application/pdf, application/json' \
--output 'AVR-document.pdf'
Include application/json in Accept so that error responses come back as JSON rather than binary.
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| id (path) | UUID | Yes | The documentId returned by Create AVR |
| companyId (query) | UUID | Yes | The company the AVR belongs to. Must match the token's company scope; otherwise COMPANY_SCOPE_MISMATCH. |
Responses
200 - Successful Response
Content-Type: application/pdf
Content-Disposition: attachment; filename="AVR-2026-0001.pdf"; filename*=UTF-8''AVR-2026-0001.pdf
Cache-Control: no-store
PDF file as binary response body. Use the filename* parameter from Content-Disposition when saving the file — it preserves Cyrillic characters in the AVR number.
What the PDF contains:
- Parties: customer (Заказчик) and performer (Исполнитель) — name, TIN, address and bank details (when provided)
- Contract number and date, or "без договора" when no contract was specified
- Document number and date
- Work line items table with columns: index, service name, date, unit, quantity, unit price, total; VAT columns (rate, amount, VAT-inclusive total) are added only when at least one line carries VAT
- Signature lines (Сдал / Принял)
- IS ESF block: KGD registration number, current status (in Russian), and for each side the signer's position, full name and signing date/time (Kazakhstan time)
For correction AVRs, the PDF prints "Исправленный АВР" with the number, date and registration number of the original.
If the AVR has not yet been registered at KGD (e.g. still in DRAFT), the PDF displays a prominent "Не зарегистрирован в ИС ЭСФ" mark.
4xx - Error Responses
| HTTP | Code | Description |
|---|---|---|
| 404 | AWP_NOT_FOUND | No AVR with this ID in the company. |
| 400 | AWP_PDF_INCOMING_NOT_SUPPORTED | The AVR is incoming (role = CUSTOMER); PDF download is currently supported for outgoing AVRs only. |
| 409 | AWP_PDF_NO_DOCUMENT | The record holds no sent AVR XML. |
| 409 | AWP_PDF_DOCUMENT_UNREADABLE | The stored XML cannot be read. |
| 400 | COMPANY_SCOPE_MISMATCH | companyId does not match the token's company scope. |
AVR Action Endpoints
The following endpoints change the status of an AVR that Docnova manages. They all share the same request body shape:
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | UUID | Yes | Docnova UUID of the calling company |
| comment | String | Yes | Reason for the action (required by KGD) |
| signerName | String | Yes | Position of the person authorizing the action, e.g. Director. Returns MISSING_SIGNER_NAME if omitted. |
5. Confirm AVR POST
Purpose of Use: The POST /api/awp/{id}/confirm endpoint is called by the customer (recipient) to confirm acceptance of a delivered AVR. The AVR must be in DELIVERED status.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}/confirm |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — company API key of the customer company |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{AVR_ID}/confirm' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"companyId": "{CUSTOMER_COMPANY_ID}",
"comment": "Services received and accepted",
"signerName": "Director"
}'
Request Parameters
See Common Request Body above. {AVR_ID} is the documentId of the AVR as seen by the customer company.
Responses
200 - Successful Response
Full AVR object (same shape as Get AVR), with status: "CONFIRMED".
| Required status | Allowed caller |
|---|---|
| DELIVERED | CUSTOMER (recipient) |
6. Decline AVR POST
Purpose of Use: The POST /api/awp/{id}/decline endpoint is called by the customer (recipient) to reject a delivered AVR. DECLINED is a final status — it cannot be reversed.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}/decline |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — company API key of the customer company |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{AVR_ID}/decline' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"companyId": "{CUSTOMER_COMPANY_ID}",
"comment": "Services not delivered as agreed",
"signerName": "Director"
}'
Request Parameters
See Common Request Body above.
Responses
200 - Successful Response
Full AVR object with status: "DECLINED".
| Required status | Allowed caller |
|---|---|
| DELIVERED | CUSTOMER (recipient) |
7. Revoke AVR POST
Purpose of Use: The POST /api/awp/{id}/revoke endpoint is called by the sender (performer) to withdraw an AVR before the customer has confirmed it. Allowed from CREATED, NOT_VIEWED or DELIVERED status. REVOKED is a final status.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}/revoke |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — company API key of the performer company |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{AVR_ID}/revoke' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"companyId": "{PERFORMER_COMPANY_ID}",
"comment": "Sent in error — withdrawing the document",
"signerName": "Director"
}'
Request Parameters
See Common Request Body above.
Responses
200 - Successful Response
AVR object with status: "REVOKED".
| Required status | Allowed caller |
|---|---|
| CREATED / NOT_VIEWED / DELIVERED | PERFORMER (sender) |
8. Initiate Termination POST
Purpose of Use: The POST /api/awp/{id}/initiate-termination endpoint starts the two-step mutual termination process for a confirmed AVR. Either party (performer or customer) can initiate. After this call the AVR moves to IN_TERMINATING and waits for the other party to call Confirm Termination.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}/initiate-termination |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — company API key of either party |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{AVR_ID}/initiate-termination' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"companyId": "{COMPANY_ID}",
"comment": "Mutual agreement to terminate",
"signerName": "Director"
}'
Request Parameters
See Common Request Body above.
Responses
200 - Successful Response
AVR object with status: "IN_TERMINATING".
| Required status | Allowed caller |
|---|---|
| CONFIRMED | PERFORMER or CUSTOMER |
9. Confirm Termination POST
Purpose of Use: The POST /api/awp/{id}/confirm-termination endpoint completes the two-step termination process. It is called by the party that did not initiate the termination. On success the AVR moves to TERMINATED — a final, irreversible status.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}/confirm-termination |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — company API key of either party |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{AVR_ID}/confirm-termination' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"companyId": "{COMPANY_ID}",
"comment": "Termination confirmed",
"signerName": "Director"
}'
Request Parameters
See Common Request Body above.
Responses
200 - Successful Response
Full AVR object with status: "TERMINATED".
| Required status | Allowed caller |
|---|---|
| IN_TERMINATING | PERFORMER or CUSTOMER |
10. Create Corrected AVR POST
Purpose of Use: The POST /api/awp/{id}/create-corrected endpoint creates a correction AVR for a confirmed document that contains an error. The original AVR must be in CONFIRMED status. Either party can initiate a correction.
This endpoint is synchronous — unlike send-document-async-json, it does not return a trackingId. It signs, uploads to KGD and returns the new AVR record in a single response.
Endpoint Information
| Property | Value |
|---|---|
| URL | /api/awp/{id}/create-corrected |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://api-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | r-auth: JWT token — company API key of either party |
Example Request
curl --location 'https://api-stage.docnova.ai/api/awp/{ORIGINAL_AVR_ID}/create-corrected' \
--header 'r-auth: {JWT_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"companyId": "{COMPANY_ID}",
"number": "AVR-2026-001-C1",
"avrDate": "06.11.2026",
"performedDate": "05.11.2026",
"senderTin": "123456789012",
"senderName": "TOO Performer",
"senderAddress": "Almaty",
"senderRegistrationType": "ENTERPRISE",
"recipientTin": "987654321098",
"recipientName": "TOO Customer",
"recipientAddress": "Almaty",
"recipientRegistrationType": "ENTERPRISE",
"currencyCode": "KZT",
"totalNdsAmount": 0,
"totalSumWithTax": 120000,
"totalSumWithoutTax": 120000,
"totalTurnoverSize": 120000,
"senderSignerName": "Генеральный директор",
"works": [
{
"name": "Услуги по аренде машин и оборудования для строительства промышленного и гражданского",
"gsvsCode": "77.32.10.01",
"quantity": 1,
"measureUnitCode": "5114",
"unitPriceWithoutTax": 120000,
"sumWithoutTax": 120000,
"sumWithTax": 120000,
"turnoverSize": 120000
}
]
}'
Request Parameters
The body uses the same AVR fields as send-document-async-json (see Create AVR — JSON Format). Key differences:
| Field | Note |
|---|---|
| {id} (path) | The documentId of the original confirmed AVR |
| number | A new unique number for the correction document, e.g. AVR-2026-001-C1 |
| companyId | Required in the body (in addition to the token scope) |
| senderSignerName | Required in the body (same as Create AVR) |
| awpType | Do not include — Docnova sets it to FIXED automatically |
| parentAwpId | Do not include — Docnova sets it from the {id} path parameter |
Responses
200 - Successful Response
{
"id": "b852b2d9-da60-4aeb-a9f0-c8ffb220ee62",
"internalId": "AWP-2026-00220",
"status": "NOT_VIEWED",
"role": "PERFORMER",
"kgdAwpId": "946382",
"kgdReference": "AVR-2026-001-C1",
"kgdRegistrationNumber": "AKT-123456789012-261106-00441822",
"corrected": true,
"parentAwpId": "dcde9582-4842-43ee-af34-d9e9e1b58b29",
"totalSumWithTax": 120000
}
| Field | Description |
|---|---|
| corrected | Always true for correction AVRs |
| parentAwpId | Docnova ID of the original AVR that was corrected |
| status | Starts at NOT_VIEWED — follows the same lifecycle as a new AVR |
| Required status | Allowed caller |
|---|---|
| CONFIRMED | PERFORMER or CUSTOMER |