> For the complete documentation index, see [llms.txt](https://api.qvalia.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://api.qvalia.io/qvalia-developer-tools.md).

# Qvalia Developer Tools

<figure><img src="https://1527578822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FS4MbRBCDJsKGrYU4ahuP%2Fuploads%2FD9v8NVn9wjB0qgLdhzst%2Fimage.png?alt=media&amp;token=e44a8efe-570d-4c70-b415-884ea996af48" alt="" width="375"><figcaption></figcaption></figure>

Our APIs and onboarding team ensure a swift integration into your systems and processes. Qvalia integrates with major ERPs and accounting software.

All Qvalia APIs are [REST](http://en.wikipedia.org/wiki/Representational_State_Transfer) based and we use both JSON and XML request and response payloads. All message formats are based upon [UBL](https://en.wikipedia.org/wiki/Universal_Business_Language) and our JSON format is a representation of the XML called UBL JSON by OASIS Open group. We strive to use the REST standards for response codes and “verbs” (e.g. GET and POST).

The Qvalia API has two separate endpoints for our Production and a Test environment.

> `https://api.qvalia.com/       [Production]`
>
> `https://api-test.qvalia.com/  [Staging / Sandbox]`

{% hint style="warning" %}
You must obtain a Qvalia account prior to using (or testing) the API!
{% endhint %}

***

Want to jump right in?

{% content-ref url="/pages/aqVKtBOtEKGcwRhxygtW" %}
[Quick Start](/quick-start.md)
{% endcontent-ref %}

{% content-ref url="/pages/PHqCxQlGl0DgM5ZRIwr9" %}
[APIs](/api-documentation/apis.md)
{% endcontent-ref %}

***

### Authentication <a href="#authentication" id="authentication"></a>

Every request is authenticated either with a long-lived **API key** or with a short-lived\
**JWT access token**:

* **API key** — sent as `Authorization: <api_key>`. You will find yours in the Qvalia\
  portal under API & SFTP settings, and you get a separate key for Production and Test.
* **JWT access token** — exchange your API key for a token at `POST /token/{accountRegNo}`\
  and send it as `Authorization: Bearer <token>`. Tokens expire after one hour. Partners\
  can also request a token scoped to a child account.

See [Ways to authenticate](/api-documentation/apis/ways-to-authenticate.md) for all three flows, including the OAuth2-style client-credentials exchange.

{% hint style="info" %}
All requests use HTTPS with a minimum of TLS 1.2.
{% endhint %}

### Parameters

Some of our APIs have the possibility to provide parameters for e.g. filtering. These parameters are sent as a query string and the options are listed per endpoint under the technical API documentation.

### Error handling <a href="#error-handling" id="error-handling"></a>

Codes in the 2xx range indicate success. Codes in the 4xx range indicate a problem with\
the request - the data sent, a missing parameter, or the credentials used. Codes in the\
5xx range indicate a problem on our side; contact Qvalia Helpdesk if you receive any 500 errors!

Every error carries the same JSON body:

```
{
  "status": "error",
  "type": "E_VALIDATION",
  "data": "Invalid payload",
  "metadata": { "debug_error_message": "…", "debug_error_code": 422 }
}
```

Branch on `type`, which is stable, rather than on `data`, whose wording may change.

| `type`                                                          | Status |
| --------------------------------------------------------------- | ------ |
| `E_BAD_REQUEST`                                                 | 400    |
| `E_UNAUTHORIZED_CLIENT`, `E_CLIENT_UNSUCCESSFUL_AUTHENTICATION` | 401    |
| `E_MISSING_PERMISSION`                                          | 403    |
| `E_MISSING`                                                     | 404    |
| `E_CONFLICT`                                                    | 409    |
| `E_VALIDATION`, `E_PEPPOL_PARTICIPANT_SMP_LOOKUP`               | 422    |
| `E_RATE_LIMITED`                                                | 429    |
| `E_INTERNAL_PROXY_ERROR`                                        | 500    |

`metadata` varies by error type and is omitted entirely on a `500`. The SCIM endpoints are\
the one exception: they return the SCIM Error schema from RFC 7644 as\
`application/scim+json`, because provisioning connectors expect it.

### **Support**

You can always contact Qvalia Helpdesk through your Qvalia Sales representative or by using our Helpdesk e-mail (see your Qvalia Account for details).

### **Coding**

We use Node.js in-house, and JSON is our format of choice, however, as many ERP and Financial systems are using XML we have opted to add support for both formats in our API. You can freely swap between XML and JSON, just by using different headers:

Omitting `accept` or `content-type` headers, we'll default to JSON!

| Format         | GET                        | POST                             |
| -------------- | -------------------------- | -------------------------------- |
| XML            | `accept: application/xml`  | `content-type: application/xml`  |
| JSON (default) | `accept: application/json` | `content-type: application/json` |

*Node.js sample code for calling the API for sending a JSON request could look like:*

```javascript
const https = require('https');

async function httpsPost(registrationNumber, data) {
  const options = {
    hostname: 'api-test.qvalia.com',
    path: `/transaction/${registrationNumber}/invoices/outgoing`,
    port: 443,
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: '412ee738......d3e469a7'
    }
  };

  return new Promise((resolve, reject) => {
    const req = https.request(options, (res) => {
      const chunks = [];
      res.on('data', (chunk) => chunks.push(chunk));
      res.on('end', () => resolve(JSON.parse(Buffer.concat(chunks).toString())));
    });
    req.on('error', reject);
    req.write(JSON.stringify(data));
    req.end();
  });
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://api.qvalia.io/qvalia-developer-tools.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
