Zenvoices logo
Zenvoices logo

Public API documentation

Introduction

This document describes the public REST API of Zenvoices.

Refer to chapter Available APIs for an overview of supported featrues.

Getting started

Register for API access

If you don’t have access to a Zenvoices user/tenant yet, start your free trial here.

Grant API access to a user

The Zenvoices public API uses access tokens for authentication. An access token can be retrieved by sending user login credentials to POST /api/TokenAuth/TokenLogin. API requests are executed with the permissions of the user used for authentication. Users don’t have API access by default, therefore we first need to grant API access to a user of your tenant.

Go to Manage / Organisation / Users in the Zenvoices portal. Create a new user which is only used for API access (recommended) or use an existing user. Edit the permissions of the user and grant the API permissions you’d like to use.

Note: users with only API access are not billed.

Get an access token

Call POST /api/TokenAuth/TokenLogin with your user credentials to get an access token. Access tokens are valid for 1 day and are used to authenticate API requests.

Example cURL command:

curl -X 'POST' \
  'https://app.zenvoices.com/api/TokenAuth/TokenLogin' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json-patch+json' \
  -d '{
  "userNameOrEmailAddress": "your-api-user-username",
  "password": "your-api-user-password",
  "tenancyName": "your-tenant-name",
}'

Note that tenancy name is the organisation code of your Zenvoices organisation.

Example response:

{
  "result": {
    "accessToken": "access-token",
    "expireInSeconds": 86400,
    "loginVerificationCode": null,
    "requiresTwoFactorVerification": false,
    "twoFactorAuthProviders": null,
    "refreshToken": "refresh-token",
    "refreshTokenExpireInSeconds": 31536000
  },
  "targetUrl": null,
  "success": true,
  "error": null,
  "unAuthorizedRequest": false,
  "__abp": true
}

In the response above the result.accessToken property contains the access token. In subsequent requests you must include this access token in the Authorization header with value “Bearer <access-token>”.

Once the access token has expired, you can get a new access token by calling the TokenLogin endpoint again or you can use the POST ​/api​/TokenAuth​/RefreshToken endpoint to retrieve a new token using the provided refresh token.

Make your first API call

For example call POST /public-api/v1/air/processDocument using the following cURL command:

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'Authorization: Bearer <your-access-token>' -d '{ \ 
   "url": "https://your-domain/document.pdf", \ 
   "fileName": "document.pdf", \ 
   "legislation": "nl",   \ 
 }' 'https://app.zenvoices.com/public-api/v1/air/processDocument'

Go to our Swagger UI to discover all available operations and parameters.

Authentication

API calls are authenticated by providing an Authorization header using the Bearer scheme. An access token and refresh token can be retrieved by passing user login credentials to POST /api/TokenAuth/TokenLogin or passing a refresh token to POST ​/api​/TokenAuth​/RefreshToken. API requests are executed with the permissions of the user used for authentication. We recommend using a separate user for API access.

Example Authorization header:

Authorization: Bearer <your-access-token>

Example cURL request to retrieve an access token:

curl -X 'POST' \
  'https://app.zenvoices.com/api/TokenAuth/TokenLogin' \
  -H 'accept: text/plain' \
  -H 'Content-Type: application/json-patch+json' \
  -d '{
  "userNameOrEmailAddress": "your-api-user-username",
  "password": "your-api-user-password",
  "tenancyName": "your-tenant-name",
}'

Example of an authenticated cURL request with an access token:

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'Authorization: Bearer <your-access-token>' -d '{ \ 
   "url": "https://your-domain/document.pdf", \ 
   "fileName": "document.pdf", \ 
   "legislation": "nl",   \ 
 }' 'https://app.zenvoices.com/public-api/v1/air/processDocument'

Paging and sorting data

List endpoints support paging and sorting data.

Use the maxResultCount and skipCount input parameters to receive data in pages. The maximum result count per page is 250.

Use the sorting input parameter to sort data. The value of this parameter must be in the format: “[fieldname] [asc/desc], [fieldname] [asc/desc], …”. Sorting on all response fields is supported. If no sorting parameter value is provided, results will be sorted on the primary key.

Error handling

Error kindHTTP response codeDescription
Invalid input400 This error is returned when invalid input is provided. error.validationErrors of the response body contains a list of invalid fields with related errors.
Unauthorized401, 403This error is returned when you’re not authorized to access the request resource.
Entity not found404This error is returned when a requested entity doesn’t exist.
Too many requests429This error is returned when the rate limit of an endpoint is reached.
General error500This error is returned when an error occured during request processing. Refer to error.message in the response body for details about the error.

Error messages are returned in the language that is configured for the authenticated user. You can override the user language by including the Abp.Localization.CultureName header in requests. Valid values are: nl (Dutch) and en (English).

Webhooks

The Zenvoices public API supports webhooks, which are “user-defined HTTP callbacks”. They are triggered by an event. When that event occurs, the source site makes an HTTP request to the URL configured for the webhook. Users can configure them to cause events on one site to invoke behavior on another. It’s a publish/subscribe system.

Webhook subscriptions can be created for all companies or for specific companies.

Payload format

Webhook calls have JSON payload with the following data structure:

  • Id (string): unique id of the webhook call
  • WebhookEvent (string): event name (see supported events section)
  • Attempt (int): attempt number
  • Data (object): event specific payload (see supported events section)
  • CreationTimeUtc (string): creation time of the webhook attempt in ISO 8601 format

Example:

{
"Id": "82479677-bed5-4543-82e1-4043854b3e7a",
"WebhookEvent": "App.FinancialTransaction.Exported",
"Attempt": 1,
"Data": {
"tenantId": 3332,
"administrationId": 12213,
"financialTransactionId": 1305229
},
"CreationTimeUtc": "2023-03-29T09:54:47.8028248Z"
}

Supported events

NameDescriptionExample JSON payload
App.FinancialTransaction.ExportedTriggers when a financial transaction has been successfully exported.{
tenantId: 1234,
administrationId: 1234,
financialTransactionId: 1234
}

Managing webhook subscriptions

Webhook subscriptions can be managed in the Zenvoices portal using Manage / Organisation / Webhook subscriptions (permission must be granted) or using the webhook subscriptions endpoints of our public API.

Security

Every webhook notification contains an HMAC SHA256 hash signature. It creates a signature by hashing the HTTP request’s body. Your application which subscribed to a webhook should hash the received body and check whether it is equal with received one, to ensure it has not been modified by others. For hashing the secret key is used that you configured for the webhook subscription.

Retry mechanism and auto subscription deactivation

If your webhook URL is (temporarily) unavailable, we will retry the notification 5 times with an exponential backoff strategy.

When fifteen consecutive attempts fail, the webhook subscription will be deactivated. You can reactivate the webhook subscription manually in this case.

Limits and quotas

Max. requests per second per endpoint*10
Max. items per page250

* HTTP response code 429 is returned when the request limit is reached.

Data privacy and security

  • Zenvoices is governed by strict standards regarding the privacy and protection of customer data. We take strong measures to protect your data from unauthorized persons or improper access.
  • Zenvoices is ISO 27001:2017 and 9001:2015 certified and uses ISO 27001 certified infrastructure for hosting and data storage.
  • More information about data privacy can be found in our privacy statement and data processing agreement.
  • More information about security can be found here.

Client libraries

Currently no pre-built client libraries are available, but you can easily create your own client by leveraging our OpenAPI 2.0 specification, which is available on https://app.zenvoices.com/swagger/index.html?urls.primaryName=Zenvoices%20public%20API%20v1. For example, you can use Swagger Codegen to generate client libraries for languages such as C#, Java, PHP, Python, Perl, etc.

Swagger UI

Swagger UI is available on https://app.zenvoices.com/swagger/index.html?urls.primaryName=Zenvoices%20public%20API%20v1.

If you’re logged in to the Zenvoices portal (https://app.zenvoices.com), try out requests are authenticated as the user you’re currently logged in as.

If you’d like to authenticate try out requests as another user, login as this user in the Zenvoices portal or ensure you’re logged out in the Zenvoices portal (!) and click the login button in the Swagger UI header. Note the latter only works when you’re not already logged in to the Zenvoices portal.

Available APIs

Accounting systems

This API allows you to list available accounting system connectors.

Administrations

This API is used to list administrations (companies) and get administration details. Only administrations that are granted for the authenticated user are accessible.

Automatic invoice recognition (AIR)

This API allows the use of Zenvoices automatic invoice recognition (AIR) machine learning technology to extract key-value pairs and line items from invoice and receipt documents. It outputs structured data with details of the extracted values. You can train your own machine learning models to improve accuracy by providing feedback on recognition results.

Supported fields

Header fields
Field nameData typeExtracts single or multiple values?Has confidence?Supports training?Description
InvoiceNumberStringSingleYesYesInvoice number.
InvoiceDateDateSingleYesYesDate the invoice was issued.
DueDateDateSingleYesYesDate invoice payment is due.
CurrencyStringSingleYesYesISO 4217 currency code.
TotalAmountInclTaxNumberSingleYesYesTotal amount including VAT (TotalAmountExclTax + sum of tax line amounts)
TotalAmountExclTaxNumberSingleYesYesTotal amount excluding VAT
TaxLineStringMultipleFalseYesTax amount, tax rate and base amount separated by a semicolon (;). Up to three tax line fields can be extracted. Only tax lines with rates of the given legislation are extracted.
InvoiceCocNumberStringSingleNoNoChamber of commerce number.
InvoiceCustomerIdentifierStringSingleNoNoCustomer identifier.
AccountEmailStringSingleNoNoE-mail address.
InvoiceIBANStringSingleNoNoIBAN (bank account number).
AccountPostalCodeStringMultipleNoNoPostal code.
InvoiceVatNumberStringSingleNoNoVAT number.
YourReferenceStringMultipleNoNoYour reference numbers (i.e. reference numbers of the invoice recipient)
StructuredPaymentReferenceStringSingleNoNoStructured payment reference. Supported formats: ISO 11649 Creditor Reference, Belgian OGM (gestructureerde medeling).
TaxReverseChargedKeywordBooleanSingleNoNoBool indicating if tax is reverse charged.
InvoiceKeywordBooleanSingleNoNoBool indicating if the document is an invoice. If false, the document is a receipt.
CreditKeywordBooleanSingleNoNoBool indicating if the document is a credit note. If True and extracted amounts are positive, you should change their sign to make them negative.
YourOrderNumberStringMultipleYesYesPurchase order number of the invoice recipient.
ContractNumberStringMultipleYesYesContract number.
Line items

Line items are only extracted if the extractLineItems property is set to True in the POST/public-api/v1/air/processDocument call. Line item recognition is currently available as a private beta. Please contact us if you’re interested in testing this feature.

For each line item a confidence score is provided.

Field nameData typeDescription
DescriptionStringDescription of the line.
ProductCodeStringProduct or item code.
QuantityNumberQuantity of the line.
PriceNumberPrice of the line.
AmountNumberAmount of the line (quantity * price).
TaxAmountNumberTax amount of the line.
TaxRateNumberTax rate of the line (e.g. 0.21 means 21 %)
ReferenceNumberStringReference numbers of the line.
OrderNumberStringPurchase order number of the line.
LedgerAccountCodeStringLedger account code of the line.

Excluding values from extraction

Using the “excludedValues” parameter of POST /public-api/v1/air/processDocument you can specify which field values should be excluded from extraction. For instance, if you’d like to extract data from purchase invoices you can exclude known customer account identifiers (such as VAT number and IBAN) to allow AIR to extract supplier account identifiers.

Custom models

Overview

You can train custom machine learning models to improve recognition accuracy. Custom models can be created using the endpoint POST /public-api/v1/air/model/createOrUpdate.

In the request body of the POST /public-api/v1/air/processDocument endpoint you can specify which model must be used for recognition using the modelId parameter. Our AI engine combines our pretrained models with your custom model to ensure optimal recognition accuracy on all features, even if the training data amount is small.

With the endpoint POST /public-api/v1/air/validateOperationResult you can provide feedback on process document operation results. This feedback is used to generate training data for your model.

After validating operation results, use the endpoint POST /public-api/v1/air/model/train to train your model.

Providing feedback

By providing feedback on process document operation results you can improve recognition accuracy and increase confidence values.

Use the POST /public-api/v1/air/validateOperationResult endpoint to provide feedback on a operation. You can only provide feedback on operations that used a custom model.

Example request body:

{
  "operationId": "37bc8616-ce2f-40e6-ad72-896dcfa7787e",
  "correctValues": [
    {
      "fieldName": "InvoiceNumber",
      "correctValue": "20150122"
    },
   {
      "fieldName": "InvoiceDate",
      "correctValue": "2019-01-02T00:00:00.0000000"
    },
   {
      "fieldName": "TotalAmountInclTax",
      "correctValue": "121.00"
    },
   {
      "fieldName": "TotalAmountExclTax",
      "correctValue": "100"
    },
   {
      "fieldName": "TaxLine1",
      "correctValue": "21.00;0.21;100.00"
    },
   {
      "fieldName": "YourReference",
      "correctValue": "reference1;reference2;reference3"
    },
  ],
  "correctTables": [
    {
      "tableInfo": {
        "tableX0": 0.1,
        "tableX1": 0.9,
        "tableY0": 0.4,
        "tableY1": 0.8,
        "pageNumber": 1,
        "isContinuation": false
      },
      "tableHeaders": [
        {
          "tableHeaderName": "HeaderDescription"
        },
        {
          "tableHeaderName": "NoPrediction",
        },
        {
          "tableHeaderName": "HeaderQuantity"
        },
        {
          "tableHeaderName": "HeaderBasePrice",
        },
        {
          "tableHeaderName": "HeaderTaxRate",
        },
        {
          "tableHeaderName": "HeaderTaxAmount",
        },
        {
          "tableHeaderName": "HeaderTotalPrice",
        },
      ]
    }
  ]
}

Notes:

  • We recommend providing as many validated (correct) values as possible.
  • Not providing correct values:
    • Not providing a correct value of a non amount field means the predicted value is incorrect, unless there is no predicted value.
    • Not providing a correct value of an amount field has no effect.
  • If provided amounts are not found in the document, validation has no effect.
  • Field names are case sensitive and may only occur once in the CorrectValues collection.
  • CorrectValue values are formatted as strings using the following formats:
    • Date: ISO 8601 format, e.g. “2019-01-02T00:00:00.0000000”
    • Number: “.” is used as decimal separator, no thousand separator
    • TaxLine’s: “{tax amount};{tax rate};{base amount}”, e.g. “21.00;0.21;100.00”
    • Multiple extraction fields: use a semicolon separated string, for example “correct value1; correct value2”
  • After providing feedback, a model must be retrained to let the model take advantage of the new training data.

Line item recognition

Line item recognition feedback can be provided using the CorrectTables property. Correct tables requires a “tableInfo” field and a “tableHeaders” field. Currently it is possible to fine tune the table bounds detection (location of the table in the page), and the table header classification.

Notes:

  • Table bounds should be normalized, from 0 to 1.
  • pageNumber is indexed from 1.
  • isContinuation = true means this table is a continuation of the previous table in the list of correctTables.
  • Table headers (the list of supported table headers is below) are defined from left to right. Use the NoPrediction header name for a column that is not in the supported list. It is currently not possible to train column types for tables without headers.

Please refer to our Swagger documentation for more details.

The following table header names are supported:

  • HeaderTotalPrice
  • HeaderTaxAmount
  • HeaderTaxRate
  • HeaderBasePrice
  • HeaderQuantity
  • HeaderProductCode
  • HeaderDescription
  • HeaderOrderNumber
  • HeaderReferenceNumber
  • HeaderLedgerAccount
  • NoPrediction
Training a model

You can train a model using POST /public-api/v1/air/model/train. Training is performed asynchronously and the training time depends on the amount of training data. A minimum of ~25 validated operation results is required before training is possible.

Using POST /public-api/v1/air/model/list (and checking the fields lastTrainingTime and isTrainingScheduled) you can verify if training is finished and has succeeded.

Data type value formatting

Extracted values are encoded as strings using the formats described in the table below.

Data typeFormatExample value
DateISO 8601 format“2019-01-02T00:00:00.0000000”
Number“.” is used as decimal separator, not as thousands separator“12345.12”
Boolean“True” or “False”“True”

Limits and quotas

Supported document types.pdf, .docx, .doc, .xlsx, .xls, .eml, .jpg, .jpeg, .png, .bmp
Supported legislations*nl, gb, de, be, pl, fr, es, usa
Supported document culturesnl, en, es, fr, de, pl
Max. document file size25 MB (after base64 encoding)
Max. document dimensions10.000 x 10.000 pixels
Max. document pagesNo limit, but at most 50 pages are processed
Operation result lifetime48 hours
Max. number of excluded feature values50
Max. number of ML models50**
Minimum time between model training operations2 * average training time from the last 10 training operations

* Legislations are used for tax amount extraction only.

** Support can increase this limit on request.

Data storage

  • Raw input documents are deleted when a process document operation finishes.
  • If no custom model is used, operation results are deleted ~48 hours after the operation was finished.
  • If a custom model is used, operation results and training data are stored until manual deletion of the model.

Billing

  • The AIR API is available in all Zenvoices subscriptions (including Lite).
  • One transaction is charged per five pages, with a maximum of ten transactions per document.
  • Purchasing transaction bundles allows you to save up to 46% on transaction costs.
  • See our terms of use and pricing page for transaction pricing and more information.

Financial transactions

This API allows you to list financial transactions and get financial transaction details.

Inbox

This API allows you to upload documents to the inbox of an administration.

Purchase orders

This API allows you to create, edit, delete and list purchase orders of an administration. To use this API the purchase order master data source of the administration must be configured to API.

Products

This API allows you to create, edit, delete and list products of an administration. To use this API the products master data source of the administration must be configured to API.

Users

This API allows you to list users and get user details including permissions.

Webhooks

This API allows you to manage webhook subscriptions.

Support & SLA

Changelog

  • 06-10-2023: added YourOrderNumber and ContractNumber fields to the AIR API.
  • 16-08-2023: added procuratorStatusChanges to the response of GET /public-api/v1/financialTransaction/{financialTransactionId}
  • 19-05-2023: extended error handling section with localization information.
  • 27-12-2022: added products and purchase orders endpoints.
  • 13-12-2022: added webhooks.
  • 29-7-2022: changed authentication docs to recommend usage of POST /api/TokenAuth/TokenLogin instead of POST /api/Account/Authenticate (which is obsolete).
  • 23-5-2022: increased AIR API max document file size from 10 MB to 25 MB, remove image limit of 4 MB and increased max. document dimension size from 3200 x 3200 to 10.000 x 10.000 pixels.
  • 19-3-2022: changed rate limit from max. 10 request per second to max. 10 requests per second per endpoint.
  • 14-12-2021: fixed inbox documents attachment not being visible after uploading an inbox document.
  • 02-09-2021: added the ability to sort lists by specifying the new Sorting parameter.
  • 09-07-2021: changed AreAllAdministrationsGranted field value from user to global level (i.e. also considering role permissions) in endpoint GET /public-api/v1/user/{userId}.
  • 30-06-2021: fixed incorrect values of GrantedAdministrationIds field in endpoint GET /public-api/v1/user/{userId}.
  • 11-06-2021:
    • Added users endpoints
    • Added accounting systems endpoints
    • Added downloadUrl property to FinancialTransactionAttachmentDto (GET /public-api/v1/financialTransaction/{financialTransactionId})
  • 12-05-2021:
    • Added totalCount property to the response of endpoints that support paging.
    • Added enabledFeatures property to the respone of endpoint GET /public-api/v1/administration/{administrationId}
    • Fixed administration filter issue of endpoint POST /public-api/v1/administration/list
  • 04-05-2021: changed response date formatting of AIR end points to ISO 8601
  • 29-04-2021: initial version