---
title: "Maventa Peppol API"
canonical: https://documentation.maventa.com/peppol-api/
---

Maventa offers electronic invoicing and document exchange services for businesses and public organizations. It acts as a central hub connecting suppliers, buyers, and their systems. In addition to electronic invoicing and document exchange, Maventa provides various value-added services for invoicing and related financial processes.

This guide walks you through the integration process with the Maventa system for setting up the integration for sending and receiving invoices, with a primary focus on the Peppol network. Each stage highlights goals and outlines the necessary prerequisites before moving forward to ensure a smooth setup.

By following these steps, you’ll be well on your way to a smooth and efficient integration with Maventa.

The steps show how Maventa APIs are used directly. There are also *reference implementations* that show how the API can be access using [C#](https://gitlab.com/maventa/reference-implementation-csharp) and [Java](https://gitlab.com/maventa/reference-implementation-java).

> [!NOTE]
> **Contact us before you start building**
>
> Before you start building the integration, we recommend reaching out to our [sales team](https://maventa.com/contact#sales). They will introduce you to the service, assess your business needs, and connect you with our integration care team. Our integration care team will then provide all the necessary technical support to help you build and refine your integration. Depending on your needs, we may also arrange an integration kick-off meeting or additional training to ensure a successful implementation.

## Step 1: Become a Maventa partner

Goals:

- Become a Maventa partner
- Get access to the API
- Have your Know Your Customer (KYC) process verified

### 1.1 Get access to API

#### Get access to the testing environment

To use Maventa APIs, you need access to API keys, which requires a partner company account in our [testing environment](https://testing.maventa.com/registrations?lang=en). To obtain a partner company account, contact our integration care team at <integrations@maventa.com>.  

Once you become a partner, you'll receive credentials for our testing environment:  

- **`client_id`** – Identifies the company (in this case your partner company account) (Company UUID).  
- **`client_secret`** – Identifies the user of that company (User API key).  
- **`vendor_api_key`** – Identifies your software (Vendor API key).  

The Vendor API key is available in [Maventa UI](#maventa-user-portal-ui) under *Settings > Company settings > Software API keys*. The User API key and Company UUID can be found in the *Settings* section.  

Once you have these credentials, you can start making API calls to Maventa and building the integration.

<details>
<summary>**Question:** What is a vendor?</summary>

In Maventa, a **vendor** refers to the software that is integrated with the service. A **partner account** can have one or more vendors, each represented by a **software API key** (vendor API key). This key is used to authenticate the software when connecting to Maventa via the API.

- The **vendor API key** uniquely identifies the software connecting to Maventa.  
- A single partner account can manage multiple vendor API keys — for example, to support different software products or operations in different countries.  
- All vendor API keys are managed under the same partner account, which is the entity that owns and oversees these integrations.
</details>

#### Get access to the production environment

Before moving to the production environment, the integration must be thoroughly tested in our testing environment. Additionally, all integrators are required to complete and sign the Maventa Integration Agreement, which covers key aspects such as billing and support. This agreement will be provided by your integration contact point (sales or integration care).  

Production API keys can be obtained by following the same process as in the testing environment.

### 1.2 Verify your KYC process

All Maventa customers need to be strongly authorized. The process ensures that a person with right to represent the company has confirmed and approved the registration for the Maventa service and has accepted Terms of Service. The process is crucial for preventing potential misuse of the service.

In testing environment your vendor will be automatically marked as trusted, so you can authorize the company accounts that you create. You can start implementing and testing without being trusted.
Before going to production, your KYC process needs to be approved by Maventa.

<details>
<summary>**Question:** How to get your KYC process trusted?</summary>

During onboarding the Maventa integration team will introduce and explain the KYC process. It is crucial for Maventa to understand the onboarding of a new customer to your service. This has to be documented and aligned.
</details>

## Step 2: Register an account for a company

In the subsequent steps, you will create a new user and a new company account.

**A company** in Maventa is identified by a unique Business Identifier (BID), ensuring that only one company account exists per BID. There are two types of company accounts: **user** and **partner**.
By default, a company is registered as a **user account**, which is a standard account used to send and receive electronic documents.
A **partner account** is intended for software vendors or service providers who integrate their own software solutions with Maventa. Partner accounts can manage multiple software API keys (vendors), access additional integration tools, and support multiple clients or use cases under the same umbrella.

**A user** in Maventa is linked to a company through an email address, and the same user can be associated with multiple companies. Users can have different roles, such as **user** or **admin**, depending on their level of access and responsibilities.  
There are also **API users**, which are typically created with non-personal or placeholder email addresses. These users are intended purely for integration purposes and do not require access to the Maventa UI.

<details>
<summary>**Question:** What are the differences between user roles?</summary>

In Maventa, the difference between user and admin roles mainly relates to the level of access and control within the company account in Maventa UI:

User role:

- Can view and send/receive documents
- Can see most of the relevant data for daily operations (invoices, logs, etc.)
- Cannot manage users or change company settings.

Admin role:

- Full access to all features and settings
- Can manage users (invite/remove, assign roles)
- Can configure company settings
</details>

### 2.1 Prepare data

To proceed, ensure the following:

- You have access to the API (see step 1)
- You have the necessary company registration information: a valid BID, name of the company and other relevant registration details (see step 2.3)

For creating Belgium account, you will need a valid CBE (Crossroads Bank for Enterprises) organization number

<details>
<summary>**Question:** What company information should I use for testing purposes</summary>

You can use a made-up company with a structurally valid BID or one of your real customer's company. Maventa recommends using one of your customers, because the BID needs to be valid for Peppol registrations to work.
</details>

<details>
<summary>**Question:** What about other countries? See the table below to find the appropriate BID type required for each country.</summary>

| Country           | Supported BID type | Example business identifier (BID)                                                                                              |
|-------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------|
| Finland (FI)      | ORGNR, VAT         | Organisation number (Y-tunnus/ORGNR): 2129112-6, VAT number: FI21291126                                                        |
| Sweden (SE)       | ORGNR, SSN         | Organisation number: 212000-0142, Swedish Person Identity Number (SSN): 810101-3608, 19810101-3608                             |
| Norway (NO)       | ORGNR              | Organisation number: 111111111                                                                                                 |
| Denmark (DK)      | CVR                | CVR number: DK11111114                                                                                                         |
| Netherlands (NL)  | KVK                | KVK number: 00006662                                                                                                           |
| Estonia (EE)      | VAT                | VAT number: EE100591422                                                                                                        |
| Belgium (BE)      | EN                 | Organisation number: 0111111124, 1111111145                                                                                    |
| Germany (DE)      | VAT                | VAT number: DE100000008                                                                                                        |
| Italy (IT)        | IVA, CFI           | VAT number (Imposta sul Valore Aggiunto, IVA): IT12345670017, Fiscal Code (Codice Fiscale, CFI): SCRDVD85B24H355B, 12345670017 |
| Other countries   | -                  | Please contact Maventa's support to check the correct BID type                                                                 |
</details>
### 2.2 Create a user

Start by first creating a new user by making an unauthenticated API call to the [POST /v1/users](#operations-users-postV1Users) endpoint.

### Request

```json
{
  "vendor_api_key": "string",
  "email": "string", // Can be an email address of a real user or API user
  "first_name": "string",
  "last_name": "string"
}
```

### Response

```json
{
  "user_api_key": "string"
}
```

This returns a `user_api_key`. At this point, the user is not yet associated with any company account.

<details>
<summary>**Question:** Which email to use?</summary>

You can either create a real user (a person who can log in to the [Maventa UI](#maventa-user-portal-ui)) or an API user, which cannot log in and is solely for integration purposes.
</details>

### 2.3 Create a company

Make an unauthenticated call to the [POST /v1/companies](#operations-companies-postV1Companies) endpoint to set up the company. The user created in the previous step will be associated with this new company.

### Request

```json
{
  "vendor_api_key": "string",
  "user_api_key": "string", // API key of the user created in the previous step
  "name": "string",
  "bid": "string", // Refer to the table above for the correct BID type
  "no_vat": "boolean", // Set to true if the BID is not a VAT number
  "address1": "string",
  "post_code": "string",
  "post_office": "string",
  "city": "string",
  "country": "string",
  "email": "string" // This is the company's email address
}
```

### Response

```json
{
  "id": "string"
}
```

This returns a new company identifier often referred as `company_id`.

Note: Maventa doesn't recommend using the same user for every company you create. Even when using API users, it's better to have a unique user for each company.

### 2.4 Conclusion

You should now have:

- `company_id`, also known as `client_id` in the token creation
- `user_api_key`, also known as `client_secret` in the token creation
- `vendor_api_key`

These are needed when making an OAuth2 token to call the other endpoints.

## Step 3: Authenticate

### Prerequisites

In order to authorize the company in production in Step 3.2, you must have an approved KYC process, as detailed in [1.2 Verify your KYC process](#12-verify-your-kyc-process).

### 3.1 API authorization

From this point onward, this guide includes setting company settings, registering profiles to Peppol, sending invoices to Peppol and other routes, and fetching received invoices. The scopes you need are `company lookup invoice:send invoice:receive`.

Make a call to [POST /oauth2/token](#operations-oauth2-postOauth2Token) endpoint giving `grant_type`, `client_id`, `client_secret`, `vendor_api_key`, and `scope` to get an OAuth2 (Open Authorization) token.  
It returns an `access_token` with `token_type` being `Bearer`, which is valid for 60 minutes.

As `client_id` and `client_secret`, use the ones received in steps 2.2 and 2.3. Do not use the credentials you have for your partner company.

```json
{
  "grant_type": "client_credentials",
  "client_id": "string", // Use the company_id from step 2.2
  "client_secret": "string", // Use the user_api_key from step 2.3
  "scope": "string",
  "vendor_api_key": "string"
}
```

After you have successfully received a token, try calling the [GET /oauth2/current](#operations-oauth2-getOauth2Current) endpoint, providing the bearer token as the `authentication` header, for example `Bearer eyJ0eXAiOiJKV1QiLCJraWQi....`, to fetch information about the authenticated user and company.

You can now also try calling [GET /v1/invoices](#operations-invoices-getV1Invoices) endpoint to list sent or received invoices. The response should be an empty list, as the company has no invoices.

### 3.2 Authorize the company

Reuse the token created in the previous step or create a new token with the scope being `company`. Make a call to the [POST /v1/company/authorization](#operation-company-postV1CompanyAuthorization) endpoint with:

```json
{
  "auth_email": "the-email-of-the-user", // Can be an email address of a real user or API user
  "locale": "EN",
  "options": "{\"authorization_method\": \"this needs to be something unique per company\"}"
}
```

You must provide an identifier in `authorization_method` unique to each company to link to the authorization event (e.g., contract number, signing eventID). This will be determined in the approved KYC process, so you should already know what to put here.

After a successful authorization call, make another call to [GET /v1/company/authorization](#operations-company-getV1CompanyAuthorization) to confirm it returns `company_state = verified`.

### Conclusion

You now have:

- Knowledge on how to create an OAuth2 token and perform authenticated API calls
- A customer company that has one user and has been authorized

Now you can move on to using the account for receiving and sending documents.

## Step 4: Sending invoices

With Maventa, invoices can be sent as e-invoices through various networks, including Peppol, or through alternative fallback delivery routes like email and print. Learn more about [email invoicing](https://documentation.maventa.com/integration-guide/invoice-sending/email-invoicing/) and sending invoices through our [printing service](https://documentation.maventa.com/integration-guide/invoice-sending/printing/). You can either send the invoice to Maventa and let the system automatically determine the best delivery route based on the recipient’s data or you can force the invoice to a specific route, such as email.  

In Belgium, the primary delivery route for sending e-invoices is the Peppol network.

### Goals

- Enable seamless e-invoice sending
- Ensure efficient monitoring of sent invoices
- Quickly identify and address any errors that may occur

### Prerequisites for sending

- An authorized company
- You need to be able to generate a valid PeppolBIS 3.0 XML file (or other supported format)

### 4.1 Prepare your invoice

As the sender, you need to generate and prepare the invoice along with any necessary attachments in your system and send them to Maventa via the API.

#### Create the XML file

You need to create a [Peppol BIS 3.0](https://docs.peppol.eu/poacc/billing/3.0/) (or other supported format). This means mapping data from your system into an XML file.
Read more about [XML formats and conversions](#xml-formats-and-conversions).

<!-- ## #### Create the JSON - NOT YET IN USE TODO

In addition to the option of sending invoices to Maventa via the API as XML files, you can also send us the JSON version of the invoice. The specifications can be found HERE.  
The version is Peppol BIS 3.0 and upcoming PINT compatible, offering a future-proof and dynamic solution in case market needs and requirements change in the future.

Similarly to XML, the sending system must ensure that the JSON format remains compliant with current regulations and standards by regularly updating it in line with any new requirements.  
-->

#### Recipient lookup and routing

To ensure your invoice is sent as an e-invoice, you can perform a lookup before sending. This confirms whether the recipient can receive e-invoices, and if not, you can decide if you want to still send it using fallback delivery routes (e.g., email or print). You can either manage this lookup yourself or rely on Maventa to handle it for you. When sending invoices through Maventa, the system will perform a recipient lookup and determine the most suitable delivery route. There is specific delivery route order the system uses and it depends on the sender's country. In Belgium, the priority order is Maventa's internal network first, followed by Peppol, and then fallback routes, with email as the first option and print as the last. You can influence this routing by specifying which delivery routes are allowed or restricted either directly in the XML file or through API metadata (read more about [controlling delivery routes](#controlling-delivery-routes)).

##### Automatic lookup and routing

- Matching based on e-invoice address:

  If you provide a valid e-invoice address, such as a Peppol ID (e.g., 9925:be000000000b21) or another supported identifier, Maventa will use it to look up the recipient in e-invoice address registries and attempt direct delivery through the identified route. Adding an operator code (e.g., PEPPOL) alongside the e-invoice address forces delivery through that specific route, disabling fallback options even if delivery fails. The operator code can be specified in the API metadata or the invoice XML, depending on the format (note: Peppol BIS 3.0 does not support an operator code field).

- Recipient's business ID based lookup:

  If you don’t know the recipient’s e-invoice address, Maventa will attempt to find an e-invoice address using the recipient’s business ID from the invoice data (e.g., VAT number or national business registry number). If a matching e-invoice address is found Maventa will attempt delivery through the identified route.

> [!WARNING]
> Automatic lookup of the recipient’s e-invoicing address using just the business ID works only in the following situations:
>
> - Internal Maventa recipients
> - Finnish recipients via Finnish operator and bank networks
> - Swedish recipients via the Swedish operator network or Peppol
> - Norwegian recipients via Peppol
> - Dutch recipients via Peppol
>
> For recipients from all other countries, the full e-invoicing address must always be provided, including the scheme ID from [the eDec list](https://docs.peppol.eu/edelivery/codelists/) followed by the correct recipient ID.

- Alternative fallback delivery routes:

  If no e-invoice address is found, or if sending to the identified e-invoice address fails for any reason, Maventa can still deliver the invoice through other available routes, such as email or print. This is determined based on your account configurations, metadata given in the sending method, or data on the invoice.

<details>
<summary>**Question:** Which e-invoicing registries does Maventa use to look up recipient e-invoice addresses?</summary>

Maventa performs recipient lookups using multiple e-invoicing registries to find the correct e-invoice address for delivery. These include:

- Peppol directory – If the recipient is registered in the Peppol network, Maventa retrieves their Peppol ID and supported document types.
- Maventa’s own registry – Maventa maintains an internal registry of companies using its service, allowing invoices to be routed efficiently within its network.
- Finnish TIEKE registry – For companies in Finland, Maventa checks the TIEKE e-invoice address registry, which contains Finnish business e-invoicing details.
- Swedish NEA registry – Used for finding e-invoice addresses of companies in Sweden.
</details>

<details>
<summary>**Question:** How to use email and print as an alternative delivery routes?</summary>

**To use the email route**, the email sending functionality must be enabled on your company account. It is enabled by default when the company is created but can be toggled on or off in the company settings. The recipient's email address should be included either in the invoice XML or as a parameter (recipient_email) in the API metadata during the sending method. Additionally, make sure the email route is not disabled in the sending configuration (disabled_routes). For more details, check out the [email sending documentation](https://documentation.maventa.com/integration-guide/invoice-sending/email-invoicing/).

**To use the print route**, the print sending functionality must be enabled on your company account. The recipient's full postal address should be included in the invoice XML. Additionally make sure the print route is not disabled in the sending configuration (disabled_routes). For more details, check out the [printing service documentation](https://documentation.maventa.com/integration-guide/invoice-sending/printing/). Please note that, at the moment, we do not have a local printing solution in Belgium, so all prints are routed through our default printing country, Finland.
</details>

##### Manual lookup

To perform the lookup yourself before sending, use the [GET /v1/lookup/receivers](https://swagger.maventa.com/?urls.primaryName=STAGE+-+AutoXChange+API#/lookup/getV1LookupReceivers) method. You can search using identifiers like the company name, business ID (VAT number or national business registry number), or e-invoice address (e.g., OVT, GLN).

API Parameters

- network:

PEPPOL – for recipients in the Peppol network
INTERNAL – for recipients within Maventa’s internal network
EXTERNAL – for recipients in external registries, such as Finnish or Swedish operator networks
SPROOM – for recipients in Nemhandel (Sproom)

- eia: Use this field if you have the recipient’s full e-invoice address (EIA)
- bid: Use this field if you only have the recipient’s business ID
- name: Use this field if you only know recipient's name
- country: Use the recipient’s ISO country code to narrow down the results

> [!WARNING]
> When searching for recipients in the Peppol network, there is a known limitation with this API. To perform a Peppol Directory lookup, you must use the name field for either the recipient’s name or business ID. The bid field does not currently work for Peppol lookups. This behavior will be corrected in a future version of the lookup API, but for now, please keep this in mind when performing searches.

The purpose of the lookup is to determine whether the recipient is able to receive electronic invoices and through which delivery route. It also helps identify the recipient’s e-invoicing address, for example a Peppol participant identifier such as 9925:be000000000b21. Additionally, the lookup shows which Peppol document types the recipient supports (INVOICE or CREDIT_NOTE).

### Request URL

```json
https://ax.maventa.com/v1/lookup/receivers?network=PEPPOL,INTERNAL,EXTERNAL&name=3478209-8&country=FI&page=1&per_page=100
```

### Response

```json
[
  {
    "eia": "0216:003734782098",
    "network": "PEPPOL",
    "operator": "PEPPOL",
    "document_types": [
      {
        "document_type": "CREDIT_NOTE",
        "document_identifier": "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
        "process_identifier": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
      },
      {
        "document_type": "INVOICE",
        "document_identifier": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
        "process_identifier": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
      }
    ],
    "participant": {
      "name": "Maventa Oy",
      "country": "FI"
    }
  }
]
```

##### How to use the recipient data on invoice

Recipient information can be provided in two ways when sending an invoice through Maventa:

- In the XML file – depending on the format, this may even be mandatory (e.g., Peppol BIS 3.0).
- As parameters in the API call – if both XML and API parameters are provided, the API parameters take precedence.

If both a business ID and an Endpoint ID are included in the XML, the Endpoint ID will take priority for routing the invoice.

> [!WARNING]
> Automatic lookup of the recipient’s e-invoicing address using just the business ID works only in the following situations:
>
> - Internal Maventa recipients
> - Finnish recipients via Finnish operator and bank networks
> - Swedish recipients via the Swedish operator network or Peppol
> - Norwegian recipients via Peppol
> - Dutch recipients via Peppol
>
> For recipients from all other countries, the full e-invoicing address must always be provided, including the scheme ID from [the eDec list](https://docs.peppol.eu/edelivery/codelists/) followed by the correct recipient ID.

Example: Including e-invoice address (EndpointID) for Peppol BIS 3.0:

```xml
<cac:Party>
  <cac:EndpointID schemeID="9930">123456789</cac:EndpointID>
</cac:Party>
```

> [!WARNING]
> The EndpointID is mandatory in Peppol BIS 3.0 and must always be included.

> [!NOTE]
> When using Peppol BIS 3.0, the operator ID cannot be included in the XML. If an invoice needs to be routed via Peppol, the Peppol operator can be specified in the API metadata. Note that providing only the operator code in the metadata will work exclusively for routing through the Peppol network.

#### Invoice image and attachments

The way invoice images (like PDFs) and other attachments are included depends on the format of the invoice you are sending. They can either be embedded within the XML (e.g. Peppol BIS 3.0) or included as separate files in a ZIP package alongside the XML (e.g. Finvoice 3.0).

It is important to follow the specific requirements of each format to ensure successful processing by Maventa and proper delivery via the Peppol network. Keep in mind that not all recipients in Peppol support or display attachments — some may ignore them entirely. While including a PDF can be helpful, it is optional; the XML must always be complete and valid on its own to ensure proper processing.

##### Embedding in Peppol BIS 3.0 and other UBL-based formats

In the Peppol BIS 3.0 format (commonly used in Belgium), attachments must be embedded within the XML file as defined in the specification. Sending Peppol BIS 3.0, attachments placed outside the XML (e.g., in the ZIP file) will be ignored.

Maventa treats an embedded attachment as the invoice image only when its `AdditionalDocumentReference` carries the exact description `<cbc:DocumentDescription>CommercialInvoice</cbc:DocumentDescription>`. Every other embedded attachment is handled as a regular supporting document. See [Peppol BIS 3.0](https://documentation.maventa.com/integration-guide/invoicing-formats/peppolbis30/) for the exact XML.

##### ZIP Packaging for other formats

If you are using a format that does not support embedded attachments, you may include attachments within the same ZIP file as the XML. To ensure proper recognition of the invoice image by Maventa, the XML and the invoice image must have the same file name, e.g., 12345.xml and 12345.pdf. Other attachments do not need to match the XML filename.

##### Fallback for missing invoice image

If no invoice image is included and the chosen delivery route requires one (e.g., print), Maventa will automatically generate a visual invoice image from the provided XML data. Peppol route does not require one.

##### File size limits

To ensure reliable delivery and avoid processing issues, follow these size guidelines:

- Maximum size per attachment: 10 MB
- Maximum total package size: 100 MB

Best practice: Keep attachments as small as possible. The smaller, the better for performance and delivery success.

<details>
<summary>**Question:** What filetypes are supported?</summary>

Only the following filetypes are supported when sending through Maventa: .pdf - RECOMMENDED, .tif, .tiff, .jpg, .jpeg, .png, .gif, .txt, .xml, .xls, .xsl, .xlsx, .html, .htm, .aix, .doc, .docx, .ods.

Note! only the following [MIME types](https://docs.peppol.eu/poacc/billing/3.0/codelist/MimeCode/) are supported in PEPPOL.
</details>

<details>
<summary>**Question:** What are the requirements for naming attachment files?</summary>

All files sent through the service must follow these naming rules:

- File names may only include letters (A–Z), numbers (0–9), periods (.) and underscores (_)
- Special characters are not allowed
- The file name must not exceed 50 characters in length
</details>

#### Validate before sending

Validating your invoice XML *before* sending is optional, but it is required for all invoices sent to Peppol. If you have your own validation process or are confident that your XML invoice is valid, you can skip this step. Maventa will perform validation during the sending process, but doing a pre-send validation can help you catch any issues earlier.

Call the [POST /v1/validate](https://swagger.maventa.com/?urls.primaryName=STAGE+-+AutoInvoice+Validator+API#/validation/post_v1_validate)

### 4.2 Send the invoice

All Maventa company accounts have invoice sending enabled by default — you’re ready to go from day one.
Before sending, make sure your invoice is properly constructed and, ideally, validated.

To send an invoice through Maventa, send the XML file along with required parameters using the following API:

[POST /v1/invoices](#operations-invoices-postV1Invoices).

After successful sent, Maventa reponds with a UUID (invoice ID), which should be saved in your system to track delivery status and updates.

#### Key API parameters

- Recipient’s e-invoicing address (recipient_eia) and operator `PEPPOL` (recipient_operator) can be provided to force routing through Peppol. Note: If recipient details are provided both in the API request and in the XML file, the API parameters will override the values in the XML.
- Recipient’s email address can also be given for email delivery fallback in the API request

#### Controlling delivery routes

If you want to restrict certain delivery routes, use the disabled_routes parameter. This gives you control over which route (einvoice, email, print) are allowed or blocked for each invoice. Adding an operator code (e.g., PEPPOL) alongside the e-invoice address forces delivery through that specific network, disabling fallback options even if they would not be disabled separately. Read more about [recipient lookup and routing](#recipient-lookup-and-routing).

Few important things to remember:

- Adding an operator code (e.g., PEPPOL) alongside the e-invoice address forces delivery through that specific network, disabling fallback options even if delivery fails
- If recipient details are provided both in the API request and in the XML file, the API parameters will override the values in the XML
- Remember to store the invoice ID for tracking purposes

### 4.3 Follow up and handle errors

After sending the invoice and securely storing its UUID, it's important to monitor its progress. We recommend using [**webhooks**](#webhooks) for real-time tracking. As a backup, you can also use **polling** to check the invoice status.

#### Register for webhook notifications for sent invoices

Use the following API to register webhook for sent invoice events: [POST /v1/company/notifications](#operations-company-postV1CompanyNotifications):

Example registering for DELIVERED, DELIVERY_CONFIRMED and FAILED events for invoices:

### Request

```json
{
  "destination_type": "WEBHOOK",
  "destination": "https://your.example/endpoint",
  "events": [
    "DOCUMENTS.INVOICE.DELIVERED",
    "DOCUMENTS.INVOICE.DELIVERY_CONFIRMED",
    "DOCUMENTS.INVOICE.FAILED"
  ]
}
```

### Response

```json
{
  "id": "d726d240-4631-483e-a4e3-61bbefa0e7b7",
  "destination_type": "WEBHOOK",
  "destination": "https://your.example/endpoint",
  "events": [
    "DOCUMENTS.INVOICE.DELIVERED",
    "DOCUMENTS.INVOICE.DELIVERY_CONFIRMED",
    "DOCUMENTS.INVOICE.FAILED"
  ]
}
```

Maventa will call the specified endpoint with an example payload like this when invoice is delivered:

```json
{
  "event":"DOCUMENTS.INVOICE.DELIVERED",
  "company_id":"xxxxe05d-42f0-4e76-acd6-968ab455xxxx",
  "event_timestamp":"2019-11-23T12:03:48+02:00",
  "event_data": {
    "invoice_id":"xxxx8354-5998-495b-8675-67bf05dexxxx",
    "invoice_number":"1003",
    "destination":"PEPPOL",
    "recipient_name":"Recipient",
    "recipient_bid":"933640000"
  }
}
```

Maventa will call the specified endpoint with an example payload like this when invoice sending fails:

```json
{
  "event":"DOCUMENTS.INVOICE.FAILED",
  "company_id":"xxxxe05d-42f0-4e76-acd6-968ab455xxxx",
  "event_timestamp":"2019-11-23T12:03:48+02:00",
  "event_data": {
    "invoice_id":"xxxx8354-5998-495b-8675-67bf05dexxxx",
    "invoice_number":"1001",
    "destination":"PEPPOL",
    "recipient_name":"Recipient",
    "recipient_bid":"933640000",
    "error_message": "Error that happened"
  }
}
```

Update you database for the invoice id in questions based on the `event`. Refer to the [Webhooks overview](#webhooks) for more details.

<details>
<summary>**Question:** What’s the difference between the DELIVERED and DELIVERY_CONFIRMED events?</summary>

The DELIVERED status means that the invoice has been successfully handed over to the chosen delivery channel (e.g., Peppol, email, print).

The DELIVERY_CONFIRMED status means that the delivery channel has acknowledged receipt or completion of delivery, but not all routes support this extra confirmation.
</details>

Keep in mind:

- An invoice marked as DELIVERED can still fail afterward — for example, if an email bounces due to a full inbox or an invalid address.
- If you receive DELIVERY_CONFIRMED, the invoice is considered fully delivered, and the status should not change to FAILED anymore.
- You can safely show both statuses to your customers — just note that DELIVERED alone doesn't always guarantee final delivery success.

#### Polling for the status

If you are unable to use the recommended webhooks, you can check the status of your invoices by polling the API. Polling can also be used as a backup in case webhook delivery fails.

Use [GET /v1/invoices/{id}](#operations-invoices-getV1InvoicesId) endpoint to poll an individual invoice by its invoice id (UUID)

Recommended Polling Frequency

- Before invoice reaches SENT status: poll every 1 hour
- After SENT status: poll once per day for up to 1 month, or until payment is received

Note: The SENT status does not guarantee successful delivery. An invoice can still fail after this point, so it is important to keep polling until the payment has been confirmed.

<details>
<summary>**Question:** How often should I poll if I already use webhooks?</summary>

As a backup, polling once a day or a few times per week is sufficient.
</details>

#### When the invoice fails

If the invoice status is FAILED or ERROR, it means all available delivery routes were attempted, but the invoice could not be delivered.

How to resolve the issue depends on the root cause:

- **Incorrect Address:** If the invoice was sent to an invalid or incorrect recipient address, simply correct the address and re-route the invoice.
- **Routing Errors:** If the issue relates to routing (e.g. delivery channel unavailable, no routes found), the invoice can be re-routed to another channel if possible.
- **Validation Errors:** If the invoice content is invalid (e.g. missing required fields or schema issues), you'll need to correct the XML and resend the invoice as a new invoice.

Note: Maventa offers a setting that enables companies to receive delivery failure notifications directly via email. This helps in identifying and addressing issues more promptly. However, we recommend that your system provides clear notifications to the user whenever action is required.

##### Re-routing an invoice

If you need to redirect your invoice to a different address or delivery route, you can do so using one of the following API endpoints, depending on the desired route:

- [PUT /v1/invoices/{id}/reroute/einvoice](#operations-invoices-putV1InvoicesIdRerouteEinvoice) - for e-invoice delivery
- [PUT /v1/invoices/{id}/reroute/email](#operations-invoices-putV1InvoicesIdRerouteEmail) - for email delivery
- [PUT /v1/invoices/{id}/reroute/print](#operations-invoices-putV1InvoicesIdReroutePrint) - for print delivery

## Step 5: Receive invoices

### Goals

- Get notifications of new invoices
- Download the new invoices
- Ensure the company is visible to suppliers in Maventa Finder and the Peppol network

### Prerequisites for receiving

- An authorized company
- Ability to handle importing PeppolBIS 3.0 XML (or other supported format) in your software

### 5.1 Activate receiving e-invoices

To receive invoices, registration to Visma and Peppol networks is required.

#### Activate Visma Network

Begin by activating the general receiving setting, known as internal receiving, or Visma network. This is necessary to activate other networks.

Call the [POST /v1​/company​/profiles](#operations-company-postV1CompanyProfiles) endpoint authenticated with `company` scope, providing the network `VISMA` and profiles `INVOICE_AND_CREDIT_NOTE`:

```json
{
  "profiles": [
    "INVOICE_AND_CREDIT_NOTE"
  ],
  "network": "VISMA"
}
```

No other parameters are needed. Expect a response of `pending`. To confirm successful registration, call the [GET /v1​/company​/profiles](#operations-company-getV1CompanyProfiles) API method and check that the status has changed to `active`.

Registering to receive is required for Peppol registration in the next step.

After this setup, it is possible to receive invoices from other Maventa customers within the internal Visma network. Furthermore, the company will appear to other Maventa customers in the Maventa Finder UI and API lookup methods.

Note that the Visma internal network does not have the same validations as the Peppol network.

#### Peppol registration

Authenticate with `company` scope and call [POST /v1​/company​/profiles](#operations-company-postV1CompanyProfiles), specifying the network as `PEPPOL` and profiles `INVOICE_AND_CREDIT_NOTE`:

```json
{
  "profiles": [
    "INVOICE_AND_CREDIT_NOTE"
  ],
  "network": "PEPPOL"
}
```

The profile `INVOICE_AND_CREDIT_NOTE` registers the up-to-date Peppol profiles relevant to the company's country. For Belgium (`BE`), the company's CBE identifier with prefix (International Code Designator) `0208` is registered. The profile covers the below document types:

- Peppol BIS Billing 3.0 Invoice
- Peppol BIS Billing 3.0 Credit Note

Maventa automatically keeps the Peppol registration updated as new invoice profiles are introduced. No need to register new profiles when the format updates, especially for `PEPPOLBIS3`.

> [!WARNING]
> Register only the profiles that are not yet registered. The request is processed as a single operation: if any profile in the `profiles` array is already registered for the company, the entire request fails and none of the new profiles are added. When adding profiles later — for example [self-billing](https://documentation.maventa.com/integration-guide/peppol/self-billing-support/) on top of an existing `INVOICE_AND_CREDIT_NOTE` registration — call [GET /v1​/company​/profiles](#operations-company-getV1CompanyProfiles) first and send only the missing profiles.

Call [GET /v1​/company​/profiles](#operations-company-getV1CompanyProfiles) again to verify that the status of the `PEPPOL` network registration is active. The error code `PROFILE_ALREADY_REGISTERED` means the profile is already registered — either because the company is registered with another Peppol access point (which must deregister it before Maventa can complete the registration), or because the profile was already registered for the company through Maventa and was included in the request again.

With registration, the company is visible with an electronic invoicing address (EIA) to suppliers in the Peppol network.

For human users, the [Peppol Directory](https://directory.peppol.eu/public) is available as a reference tool. Maventa automatically updates this directory, making your company visible there. Please note that the Peppol Directory is not part of the actual delivery infrastructure — it serves informational purposes only.

### 5.2 Fetch received invoices

To determine when an invoice has been received to a company account, you can either listen for webhook notifications or poll the API for incoming invoices. Webhooks are the preferred method, as they provide faster and more efficient delivery compared to regular polling.

#### Register for webhook notifications for received invoices

Use the following API to register for invoice receipt events: [POST /v1/company/notifications](#operations-company-postV1CompanyNotifications).
Example registering for RECEIVED events for invoices:

### Request

```json
{
  "destination_type": "WEBHOOK",
  "destination": "https://your.example/endpoint",
  "events": [
    "DOCUMENTS.INVOICE.RECEIVED"
  ]
}
```

### Response

```json
{
  "id": "d726d240-4631-483e-a4e3-61bbefa0e7b7",
  "destination_type": "WEBHOOK",
  "destination": "https://your.example/endpoint",
  "events": [
    "DOCUMENTS.INVOICE.RECEIVED"
  ]
}
```

Maventa will call the specified endpoint with an example payload like this:

```json
{
  "event":            "DOCUMENTS.INVOICE.RECEIVED",
  "company_id":       "53a4e05d-42f0-4e76-acd6-968ab4558c6f",
  "event_timestamp":  "2024-11-23T12:03:48+02:00",
  "event_data": {
    "invoice_id":     "c154feee-399b-488e-aecd-580578b140e0",
    "invoice_number": "1002",
    "origin":         "PEPPOL",
    "sender_name":    "Sender",
    "sender_bid":     "937729111"
  }
}
```

Example registering for RECEIVED events for invoices with vendor webhooks:

### Request

```json
{
  "destination_type": "VENDOR_WEBHOOK",
  "destination": "https://your.example/endpoint",
  "vendor_key": "your_vendor_api_key_here",
  "events": [
    "DOCUMENTS.INVOICE.RECEIVED"
  ]
}
```

### Response

```json
{
  "id": "d726d240-4631-483e-a4e3-61bbefa0e7b7",
  "destination_type": "VENDOR_WEBHOOK",
  "destination": "https://your.example/endpoint",
  "events": [
    "DOCUMENTS.INVOICE.RECEIVED"
  ]
}
```

Store the `event_data.invoice_id` for later processing and deduplication. Refer to the [Webhooks overview](#webhooks) for more details.

#### Polling for new received documents

If webhooks are not used, you may use [GET /v1/invoices](#operations-invoices-getV1Invoices) with parameter `direction=RECEIVED` and the time interval with `received_at_start`, and `received_at_end` to get the metadata for the list of invoices to download.

#### Download the invoice

Invoice downloading involves obtaining:

- Invoice metadata
- Invoice data
- Invoice attachments

To retrieve the invoice metadata, use the [GET /v1/invoices/{invoice_id}](#operations-invoices-getV1InvoicesId) API call without any format parameters.

To download invoice data, make the same API call with the desired format. `PEPPOLBIS30` is recommended as it's the standard format in the Peppol network.

Invoices may also contain attachments, listed in the `files` array of the invoice metadata. Download each attachment separately using [GET /v1/invoices/{id}/files/{file_id}](#operations-invoices-getV1InvoicesIdFilesFileId) with the `id` from each file entry.

Most often, attachments include *an invoice image*. It is usually a PDF document with a visual representation of the invoice data. If one is not provided by the sender, Maventa generates it.

<details>
<summary>**Question:** Then what are `ORIGINAL_IMAGE`, `GENERATED_IMAGE` and `ORIGINAL_OR_GENERATED_IMAGE` for?</summary>

Maventa can supply the PDF image: `ORIGINAL_IMAGE` provides the PDF from received invoice file, `GENERATED_IMAGE` generates a PDF based on the invoice file data, and `ORIGINAL_OR_GENERATED_IMAGE` returns or generates the PDF as needed.
</details>

## Step 6: Configure advanced settings

Use the [PATCH /v1/company/settings](#operations-company-patchV1CompanySettings) endpoint to modify company settings and activate fallback options like [email](https://documentation.maventa.com/integration-guide/invoice-sending/email-invoicing/) and [print](https://documentation.maventa.com/integration-guide/invoice-sending/printing/) routes.

A few important settings to consider:

**Email notifications (invoice_notifications):**
Enable email notifications and define recipients for:

- Send errors (on_send_errors) – Receive alerts when an invoice fails to send and ends up in an error state.
- Incoming invoices (on_receiving) – Get notified when your company account receives a new invoice.

**Duplicate invoice protection (send_invoice_general.stop_duplicate_numbers):**
Set this to true to prevent the use of the same invoice number within a one-week period. This helps avoid accidental duplicate sends from your invoicing system.

Note: If your company details change (such as postal address, billing information, etc.), please remember to update them in Maventa as well.

## Webhooks

Subscribing to receive events through the [POST /v1/company/notifications](#operations-company-postV1CompanyNotifications).

### For a single company

Once you have authenticated as a company you can call this endpoint to register a webhook for that particular company.

### For all partner’s companies

We have also a possibility to register webhooks for partners (aka vendor webhooks).

When a registration is done for a partner it covers all the companies that have been linked to the partner company’s vendor api key. The registration for a partner is a one time operation, after the registration is active the endpoint registered will receive events for all companies associated with the partner. This is the recommended way for partners to register their webhooks. Linking and unlinking the vendor api key is a requirement for this feature to fully function.

If you want to register webhooks for a partner, authenticate with the partner company credentials and specify destination_type as VENDOR_WEBHOOK when subscribing to the events.

For partner’s companies based on vendor key
There is a third posibility to register vendor webhooks based on vendor key.

This registration allows you to filter notifications based on vendor keys. This is helpful if you own multiple vendor api keys, and want notifications separately.

Registering based on vendor keys requires you to pass vendor_key in the payload.

The events are then sent as POSTs to the configured destination URL in the subscription.
Only do light processing in the webhook handler, for e.g. when receiving **DOCUMENTS.INVOICE.RECEIVED** event, persist event_data, and run a background process to download the invoice.
Our webhooks guarantees **at-least-once** delivery semantics, that means you need to **deduplicate** the invoice events in your system.

```json
POST url
Content-type: application/json

{
  "event":           "DOCUMENTS.INVOICE.RECEIVED" | "DOCUMENTS.INVOICE.DELIVERED" | "DOCUMENTS.INVOICE.DELIVERY_CONFIRMED" | "DOCUMENTS.INVOICE.FAILED",
  "company_id":      "string",
  "event_timestamp": "string",
  "event_data":      DocumentsInvoiceReceived | DocumentsInvoiceDelivered | DocumentsInvoiceDeliveryConfirmed | DocumentsInvoiceFailed
}
```

The `event` is the name of the event e.g. `DOCUMENTS.INVOICE.RECEIVED`.

The `event_timestamp` is the ISO8601 formatted time when the event was originally created.

The `company_id` is UUID of the company the event has been subscribed by.

The `event_data` is optional and its structure depends on the name of the event.

```json
type DocumentsInvoiceReceived
{
  "invoice_id":     "string",
  "invoice_number": "string",
  "origin":         "string", // e.g. "PEPPOL"
  "sender_name":    "string",
  "sender_bid":     "string"
}
```

```json
type DocumentsInvoiceDelivered
{
  "invoice_id":     "string",
  "invoice_number": "string",
  "destination":    "string", // e.g. "PEPPOL"
  "recipient_name": "string",
  "recipient_bid":  "string"
}
```

```json
type DocumentsInvoiceDeliveryConfirmed
{
  "invoice_id":     "string",
  "invoice_number": "string",
  "destination":    "string", // e.g. "PEPPOL"
  "recipient_name": "string",
  "recipient_bid":  "string"
}
```

```json
type DocumentsInvoiceFailed
{
  "invoice_id":     "string",
  "invoice_number": "string",
  "destination":    "string", // e.g. "PEPPOL"
  "recipient_name": "string",
  "recipient_bid":  "string",
  "error_message":  "string"
}
```

If the response from partner is a 2xx-response, we consider the transmission been successful. If any other response or a timeout occurs, the webhook is automatically retried for some time.

The retry strategy is:

- Retry max 24 times, once per hour

### Subscribing to Unacknowledged Webhooks

To enhance the reliability of your system's e-invoicing and document exchange processes, we recommend subscribing to the **UNACKNOWLEDGED_WEBHOOKS event** by calling the API method:[POST /v1/company/notifications](#operations-company-postV1CompanyNotifications).

Example payload:

```json
{
  "destination":      "https://example.com/webhooks/unacknowledged_webhooks?token=1234",
  "destination_type": "WEBHOOK",
  "events":           [ "UNACKNOWLEDGED_WEBHOOKS" ]
}
```

#### Why Subscribe?

- **Proactive Alerting**: If your system experiences issues and fails to respond within 24 hours, the company will receive a single notification encompassing all unacknowledged webhook events.
- **Daily Resilience**: Unacknowledged webhooks are dispatched once per company per day and will continue for up to one month, ensuring no missed alerts.

#### Retrieving Unacknowledged Webhooks

Upon receiving a notification for unacknowledged webhooks, companies can easily retrieve all failed webhooks at once by calling the API method:[POST /v1/company/notifications_resend_unacknowledged](#operations-company-postV1CompanyNotificationsResendUnacknowledged). Calling this API method will resend all unacknowledged webhook events for the company. Once an event is successfully processed by the company, any future retry attempts for sending acknowledged webhooks will stop.

The `UNACKNOWLEDGED_WEBHOOKS` event is

```json
POST url
Content-type: application/json

{
    "event":           "UNACKNOWLEDGED_WEBHOOKS",
    "company_id":      "string",
    "event_timestamp": "string"
}
```

Furthermore, if *all events* of a given subscription have been failing continuously for a month, the webhook subscriptions for the company will be disabled.

## XML formats and conversions

XML presents invoice data in a structured way. Maventa supports wide variety of XML based standard invoice formats and automatically converts the invoices from one format to another when needed. [Full list of supported formats and XML validation tool](https://swagger.maventa.com/?urls.primaryName=STAGE+-+AutoInvoice+Validator+API).

We generally recommend using the Peppol BIS 3.0 format for invoice exchange, as it is widely supported and well-suited for cross-border invoicing within the Peppol network. This format fully complies with the European EN16931 (SFS-EN 16931-1:2017) invoicing standard.

[Peppol BIS 3.0 specs](https://docs.peppol.eu/poacc/billing/3.0/)

Please note that during the conversion process from one format to another, we will take care of some of the necessary adjustments. However, when there are mandatory new data requirements for the invoice, it is essential that the sending and receiving system maintains up-to-date information to ensure compliance and smooth processing.

<!-- ## Invoice JSON

Talk about invoice JSON from both sending and receiving point of view like with the webhooks and XML formats and conversions.  -->

## Maventa user portal (UI)

The Maventa UI is a web-based user portal designed to complement API integrations by offering a visual interface for managing e-invoicing operations and supporting technical integration work. While everything that can be done in the UI is also available through the API, the UI provides a convenient and user-friendly way to view, manage, and troubleshoot integration-related tasks.

Through the Maventa UI, users can:

- Configure settings  
- Access invoice and delivery logs  
- Handle manual actions such as rerouting invoices in an error state  
- Retrieve and manage [API credentials](#get-access-to-the-testing-environment) including company UUID, user API key, and vendor API key  

Logging in to the Maventa UI requires an email-based user account.

## API endpoints

### POST /oauth2/token

OAuth2 token endpoint

The endpoint enables a registered company to obtain a OAuth 2 Bearer Token, which can be used to access the companys data in all the future API calls.
 A token will be active for 60 minutes.
 #### Scopes
 Scopes let you specify what type of access you need and limit access for granted OAuth tokens.

 | Scope | Description |
 |-------|-------------|
                            eui|  Recommended to use when integrating to EUI. Alias for eui:open, company:read, company:write, lookup, receivables:assignments, document:send, document:receive, invoice:receive, invoice:send, analysis|
                        global|                                                                                                                                         Alias for company:read, document:receive, document:send, lookup|
                       company|                                                                                                                                                                   Alias for company:read, company:write|
                        lookup|                                                                                                                                                                  grants access to the lookup operations|
              document:receive|                                                                                                                                                            grants access to document receive operations|
                 document:send|                                                                                                                                                               grants access to document send operations|
               invoice:receive|                                                                                                                                                             grants access to invoice receive operations|
                  invoice:send|                                                                                                                                                                grants access to invoice send operations|
                  company:read|                                                                                                                                      grants read access to company settings, profiles and notifications|
                 company:write|                                                                                                                                     grants write access to company settings, profiles and notifications|
                      validate|                                                                                                                                                      grants access to the AutoInvoice validator service|
       receivables:assignments|                                                                                                                                                 grants access to assignments in the collection services|
                      analysis|                                                                                                                                                                       grants access to analysis service|
               billing:reports|                                                                                                                                                                        grants access to billing reports|
partner:invoice_delivery_actions|                                                                                                                                                                grants access to partner invoice actions|
               partner:lookups|                                                                                                                                                                 grants access to partner lookup actions|
             partner:takeovers|                                                                                                                                                                      grants access to partner takeovers|
  partner:lyanthe_scan_service|                                                                                                                                                   grants access to partner lyanthe scan service actions|
          fi_bank_message:send|                                                                                                                                                        grants access to FI bank message send operations|
       fi_bank_message:receive|                                                                                                                                                     grants access to FI bank message receive operations|
    operator:documents:receive|                                                                                                                                                               grants access to fetch received documents|
       operator:documents:send|                                                                                                                                                                         grants access to send documents|
               operator:lookup|                                                                                                                                                     grants access to perform actions related to lookups|
         operator:participants|                                                                                                                                               grants access to perform actions on operator participants|
        operator:notifications|                                                                                                                                              grants access to perform actions on operator notifications|
             operator:validate|                                                                                                                                                      grants access to the AutoInvoice validator service|
operator:receivables:assignments|                                                                                                                                                 grants access to assignments in the collection services|
operator:receivables:assignments:create|                                                                                                                                          grants access to create assignments in the collection services|
 operator:receivables:webhooks|                                                                                                                                                      grants access to send collection services webhooks|
operator:receivables:account_statement|                                                                                                                                                                     grants access to account statements|
             operator:analysis|                                                                                                                                                                       grants access to analysis service|
            operator:companies|                                                                                                                                                               grants access to fetch operator companies|
             operator:takeover|                                                                                                                                                             grants access to execute a company takeover|
      operator:billing:actions|                                                                                                                                                               grants access to operator billing actions|
operator:sending_parties:write|                                                                                                                                                                  grants access to write sending parties|
operator:supplier_bank_accounts:write|                                                                                                                                                           grants access to write supplier bank accounts|
          operator:user:create|                                                                                                                                                                          grants access to create a user|
         operator:company:read|                                                                                                                                                                  grants access to read company profiles|
        operator:company:write|                                                                                                                                                                 grants access to write company profiles

 If no scope is defined, the token request will default to use the scopes ```global``` and ```company```. The granted scopes will be returned in the response.
 #### Vendor API key and license data
 To identify the application a valid ```vendor_api_key``` should be provided in the token request. Additional license data can be provided as JSON in the ```license_data``` parameter:
 ```
{
  "key": "C84411ED-5639-4B48-83D0-B718BB9DA0F7", // License key of software making the call
  "meta": {
    "licensing":   "VLS",       // Information about the licensing system
    "erp_name":    "Visma ERP", // Name of ERP
    "erp_version": "1.1",       // Current version number of ERP
    "erp_user":    "rbaardse"   // Local ERP user name
  }
}
```

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| grant_type | formData | string | yes | The grant type |
| client_id | formData | string | no | The client id |
| client_secret | formData | string | no | The client secret |
| scope | formData | string | no | Scope of the requested token |
| vendor_api_key | formData | string | no | Software API key |
| license_data | formData | string | no | License data |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Granted access token | `API_Entities_OAuthToken` |

### GET /oauth2/current

Fetch information about the authenticated user and company

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Fetch information about the authenticated user and company | `API_Entities_OAuthCurrent` |

### POST /v1/users


Create a User

**Request body**

Schema: `postV1Users`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| vendor_api_key | `string` | yes | Vendor API key |
| email | `string` | yes | User email |
| first_name | `string` | no | User first name |
| last_name | `string` | no | User last name |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 201 | Create a User | `API_Entities_ApiUser` |

### GET /v1/invoices

List invoices

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| direction | query | string | no | Received or sent invoices |
| status | query | array[string] | no | Invoice status |
| ids | query | array[string] | no | Batch of invoice IDs. Maximum of 100 per query |
| number | query | string | no | Invoice number |
| reference | query | string | no | Invoice reference |
| received_at_start | query | string | no | Received at start timestamp |
| received_at_end | query | string | no | Received at end timestamp |
| created_at_start | query | string | no | Created at start timestamp |
| created_at_end | query | string | no | Created at end timestamp |
| sort | query | array[string] | no | List of fields used for sorting.                               Ascending by default, include "-" before the field name to reverse the order (descending).                               Supported values: **received_at**                               E.g. -received_at |
| page | query | integer | no | Page to fetch |
| per_page | query | integer | no | Number of items per page, values up to 100 supported |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | List invoices | `array[Invoices_HttpApi_Entities_Invoice]` |

### POST /v1/invoices

Upload new invoice

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| file | formData | file | yes | File content. Please make sure to provide the "filename" Content-Disposition header field as well as specified in the rfc2183. |
| format | formData | string | no | File format |
| recipient_type | formData | string | no | Only in Norway, set to "consumer" to use route_order |
| recipient_eia | formData | string | no | Recipient EIA |
| recipient_email | formData | string | no | Recipient email address |
| recipient_operator | formData | string | no | Recipient operator |
| disabled_routes | formData | array[string] | no | Routes to explicitly disable |
| sender_comment | formData | string | no | Text that will be added in the email message if invoice is delivered by email |
| uuid | formData | string | no | Unique invoice uuid, generated automatically if not specified. |
| lang | formData | string | no | Set language of PDF generated by us and email what recipient receives. |
| route_order | formData | array[string] | no | Consumer routes to use. Leave empty to use default. Note! 'netbank_cvl' and 'netbank_cvl_hold' are deprecated since 05/2022. |
| recipient_phone_number | formData | string | no | Recipient phone number in international format. Used in Yes2All lookups. |
| recipient_date_of_birth | formData | string | no | Recipient date of birth in YYYY-MM-DD format. Used in Yes2All lookups. |
| recipient_ssn | formData | string | no | Recipient social security number. Used in Yes2All lookups. |
| recipient_efaktura_id | formData | string | no | Recipient unique eFaktura ID |
| b2cno_document_type | formData | string | no | B2C document type for special documents |
| payment_instruction_identifier | formData | string | no | PaymentInstructionIdentifier, used in Finnish B2C invoicing only. |
| print_settings[color] | formData | boolean | no | Enable color printing |
| print_settings[letter_class] | formData | string | no | Letter class |
| print_settings[prevent_digital_post] | formData | boolean | no | Prevent invoice from being sent to OmaPosti (Finland only) |
| print_settings[print_own_image] | formData | boolean | no | Use own image when printing (overrides company settings) |
| print_settings[allow_kivra_fi] | formData | boolean | no | Try Kivra FI before printing even if "einvoice" route is disabled in disabled_routes parameter. Only applies for B2C invoices. |
| prevent_routing | formData | boolean | no | Prevent routing of the invoice. Invoice will be set to SENT state without actually sending it anywhere. Intended use is for creating assignments without sending an invoice for the collection services |
| email_settings[xml_format] | formData | string | no | Forces the invoice to be sent via email and includes the XML attachment in the specified format |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 201 | Upload new invoice | `Invoices_HttpApi_Entities_Invoice` |

### GET /v1/invoices/{id}

Invoice details

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| id | path | string | yes | Invoice ID |
| return_format | query | string | no | Desired format |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Invoice details | `Invoices_HttpApi_Entities_Invoice` |

### GET /v1/invoices/{id}/files/{file_id}

Fetch file content

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| id | path | string | yes | Invoice ID |
| file_id | path | string | yes | Invoice file ID |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Fetch file content |  |

### PUT /v1/invoices/{id}/reroute/einvoice


Reroutes invoice via einvoice

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| id | path | string | yes | Invoice ID |

**Request body**

Schema: `putV1InvoicesIdRerouteEinvoice`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| recipient_eia | `string` | yes | Recipient electronic invoice address |
| recipient_operator | `string` | yes | Recipient operator |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Reroutes invoice via einvoice |  |

### PUT /v1/invoices/{id}/reroute/email


Reroutes invoice via email

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| id | path | string | yes | Invoice ID |

**Request body**

Schema: `putV1InvoicesIdRerouteEmail`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| recipient_email | `string` | yes | Recipient email address |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Reroutes invoice via email |  |

### PUT /v1/invoices/{id}/reroute/print


Reroutes invoice via print

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| id | path | string | yes | Invoice ID |

**Request body**

Schema: `putV1InvoicesIdReroutePrint`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| recipient_name | `string` | yes | Recipient name |
| recipient_address1 | `string` | yes | Recipient address line 1 |
| recipient_address2 | `string` | no | Recipient address line 2 |
| recipient_post_code | `string` | yes | Recipient post code |
| recipient_post_office | `string` | yes | Recipient post office |
| recipient_state | `string` | no | Recipient state |
| recipient_country | `string` | yes | Recipient country in ISO 3166-1 alpha-2 format (2 letters) |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Reroutes invoice via print |  |

### GET /v1/companies

List active companies the user has access to

List all companies without giving params, or check if user belongs to a given company.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| bid | query | string | no | Business id. |
| country | query | string | no | Country in ISO 3166-1 alpha-2 format (2 letters) |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | List active companies the user has access to | `array[API_Entities_UserCompany]` |

### POST /v1/companies


Create a Company

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| vendor_api_key | formData | string | yes | Identifies partner/ERP |
| user_api_key | formData | string | yes | The user API key |
| name | formData | string | yes | Company name. Name has to be at least 3 characters long |
| bid | formData | string | yes | Company organization number/Business ID/VAT |
| no_vat | formData | boolean | no | Deprecated, no need to give this param anymore |
| address1 | formData | string | yes | Street address |
| address2 | formData | string | no | Additional address |
| post_code | formData | string | yes | Postal number/code, |
| post_office | formData | string | yes | Post office |
| city | formData | string | yes | Registered city |
| state | formData | string | no | State of address |
| country | formData | string | yes | Country code for company, mandatory. Allowed countries FI, SE, NO, DK, NL, EE, BE, DE, LV. IT and PL are in experimental mode. |
| email | formData | string | yes | Contact email address for company |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 201 | Create a Company | `API_Entities_Company` |

### GET /v1/company/profiles

List network registrations

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| network | query | array[string] | no | Network filter |
| status | query | array[string] | no | Status filter |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | List network registrations | `array[API_Entities_CompanyProfile]` |

### POST /v1/company/profiles

Create network registration request

**Request body**

Schema: `postV1CompanyProfiles`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| profiles | `array[string]` | no | List of profile names |
| profile_version | `string` | no | Profile version, eg. EHF30, PEPPOLBIS30 |
| endpoint_id | `string` | no | Endpoint identifier |
| scheme | `string` | no | ISO6523 code of the endpoint_id scheme. eg. 0192 for NO:ORG |
| network | `string` | no | Target network, defaults to PEPPOL |
| profiles_with_extensions | `array[string]` | no | List of profile names with extensions |
| network_settings | `object` | no | Additional network settings |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 201 | Create network registration request | `API_Entities_CompanyProfile` |
| 422 | - **profile_name_conflict**: Profile is already registered for given endpoint id - **profile_eia_conflict**: Endpoint id is already in use - **profile_eia_bid_conflict**: Endpoint id does not match the company business id - **profile_not_supported**: Profile is not supported | `API_Entities_Error` |

### GET /v1/company/settings

Fetch company settings

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| fields | query | array[string] | no | Filter the response to only include requested fields.                                     Possible values: invoice_notifications, send_invoice_email, address, details, send_invoice_print, send_invoice_general, logos, email_reports, billing_details |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Fetch company settings | `API_Entities_CompanySettings_Settings` |

### PATCH /v1/company/settings

Modify company settings

### Company billing details
 ```
{
  "billing_details": {
    "electronic_invoicing_details": {
      "invoicing_eia": "Company electronic invoicing address (Billing information: The delivery method priority is following 1 = einvoice, 2 = email, 3 = print, if all below values are given. If company prefers Invoicing via normal post, invoicing_eia, invoicing_operator and invoicing_email should be left blank).",
      "invoicing_operator": "Company electronic invoicing operator address"
    },
    "invoicing_email": "info@company.com",
    "invoicing_street_address1": "My street 1",
    "invoicing_street_address2": "My street 2",
    "invoicing_post_code": "123456",
    "invoicing_post_office": "Helsinki",
    "billing_company_id": "123456"
  }
}
```




### Company email reports

```
{
  "email_reports": {
    "report_interval": "off | daily | weekly | monthly",
    "email_reports": [
      "info@company.com",
      "reports@company.com"
    ]
  }
}
```



### Company logos

```
{
  "logos": {
    "pdf": {
      "content": "Base64 encoded string of PNG or JPEG image for use as logo on generated PDF invoices"
    },
    "email_header": {
      "content": "Base64 encoded string of PNG only image for use as header image on sent email invoices"
    }
  },
}
```


### Company general settings

```
{
  "send_invoice_general": {
    "hold_multiple_recipients": false,
    "stop_duplicate_numbers": false
  }
}
```


### Company invoice print settings

```
{
  "send_invoice_print": {
    "enabled": false,
    "letter_class": "ECONOMY",
    "color_scheme": "BLACK_AND_WHITE",
    "attachment_print": false,
    "marketing_page": false,
    "use_own_pdf": false
  }
}
```


### Company details

```
{
  "details": {
    "name": "My Company Ltd",
    "email": "info@company.com",
    "website": "https://my.company.com"
  }
}
```

### Company address
 ```
{
  "address": {
    "street_address": "My street 1",
    "post_code": "123456",
    "post_office": "Oslo",
    "city": "Oslo",
    "country": "NO"
  }
}
```



### Company send invoice email related settings

```
{
  "send_invoice_email": {
    "enabled": true,
    "how_to_send": "EMBEDDED | WITH_OBJECTIONS | WITH_LINK | EMBEDDED_MERGE (only if enabled is true)",
    "reminder_frequency": 4,
    "content_data": {
      "note_to_receiver": "A message added to the receiver",
      "contact": {
        "email": "invoices@company.com (this is validated by sending a link email to the email)",
        "name": "Info User",
        "phone": "+555 55 555 5555"
      }
    }
  }
}
```


### Company invoice notification settings

```
{
  "invoice_notifications": {
    "on_receiving": {
      "enabled": true,
      "how_to_send": "OTHER_EMAIL",
      "other_email": "info@company.com"
    },
    "on_send_errors": {
      "to_user": true,
      "to_emails": [
        "info@company.com"
      ]
    }
  }
}
```

**Request body**

Schema: `patchV1CompanySettings`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| details | `API_Entities_CompanySettings_CompanyDetails` | yes | Company details |
| address | `API_Entities_CompanySettings_CompanyAddress` | yes | Company address |
| invoice_notifications | `API_Entities_CompanySettings_CompanyInvoiceNotifications` | yes | Company invoice notifications |
| send_invoice_email | `API_Entities_CompanySettings_CompanySendInvoiceEmail` | no | Company send invoices via emails |
| send_invoice_print | `API_Entities_CompanySettings_CompanySendInvoicePrintSettings` | no | Company invoice sending print settings |
| send_invoice_general | `API_Entities_CompanySettings_CompanySendInvoiceGeneralSettings` | no | Company invoice sending general settings |
| logos | `API_Entities_CompanySettings_CompanyLogos` | no | Company logos |
| email_reports | `API_Entities_CompanySettings_CompanyEmailReports` | no | Email reports |
| billing_details | `API_Entities_CompanySettings_CompanyBillingDetails` | no | Company billing details |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 204 | Settings updated successfully |  |
| 400 | - **invalid_parameters**: Request parameters are invalid | `API_Entities_Error` |

### GET /v1/company/notifications

List notification subscriptions

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | List notification subscriptions | `array[API_Entities_Notifications_Notification]` |

### POST /v1/company/notifications

Create new notification subscription

**Request body**

Schema: `postV1CompanyNotifications`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| destination_type | `string` | yes | Type of notification. Possible values: WEBHOOK, VENDOR_WEBHOOK |
| destination | `string` | yes | Notification destination. For WEBHOOK and VENDOR_WEBHOOK types, must be an HTTPS URL. |
| vendor_key | `string` | no | Name/Key of registered vendor key |
| events | `array[string]` | yes | Type of events |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 201 | Create new notification subscription | `API_Entities_Notifications_Notification` |

### GET /v1/company/authorization

Company authorization status. In order to use company account to send, receive and activate services status needs to be verified

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Company authorization status. In order to use company account to send, receive and activate services status needs to be verified | `API_Entities_CompanyAuthorizationStatus` |

### POST /v1/company/authorization


Authorize your company. Required to complete KYC process and take company account into use

**Request body**

Schema: `postV1CompanyAuthorization`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| auth_email | `string` | yes | Email to send the Visma sign request to. The person signing will be strongly authenticated. |
| locale | `string` | yes | Locale to use on the signin invitation email, visma sign portal and agreement PDF. |
| options | `string` | no | JSON string used to provide proof of KYC process. Mandatory when partner has own KYC process. |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Sign request sent | `API_Entities_CompanyAuthorization` |
| 400 | Bad request | `API_Entities_Error` |

### POST /v1/company/notifications_resend_unacknowledged

[EXPERIMENTAL] Resend unacknowledged notifications

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Request accepted. Unacknowledged webhooks for all subscriptions will get retriggered at a later point |  |

### GET /v1/lookup/receivers


Lookup for B2B document receivers

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| network | query | array[string] | yes | Networks to search from eg. PEPPOL, INTERNAL, EXTERNAL |
| eia | query | string | no | Full Electronic Address eg: 0192:123456789 |
| bid | query | string | no | Business identifier |
| name | query | string | no | Company name |
| country | query | array[string] | no | Company country in ISO 3166-1 alpha-2 format (2 letters) |
| document_type | query | array[string] | no | Document types |
| allow_eia_variants | query | boolean | no | Allow lookup to use generated eia variations, when no hits are found using the given eia |
| page | query | integer | no | Page to fetch |
| per_page | query | integer | no | Number of items per page, values up to 100 supported |

**Responses**

| Status | Description | Schema |
| --- | --- | --- |
| 200 | Lookup for B2B document receivers | `array[API_Entities_LookupEntryReceiver]` |
| 500 |  | `API_Entities_Error` |
| 503 |  | `API_Entities_Error` |


_OpenAPI spec snapshot: 2026-05-06_
