Netvisor is Visma's cloud accounting and ERP platform. This XML API gives partner integrations programmatic access to a company's accounting, sales, purchases, payroll, products, and reporting data.
All endpoints exchange XML over HTTPS. Every request is signed with a MAC (Message Authentication Code) computed over the request URL, a fixed sequence of headers, and the two private keys identifying the partner and the end-user account.
Notation. Throughout this section the symbol
&between identifiers means "string concatenation with the single literal character&between them". It is not bitwise-AND or any other operator.
1. Get credentials
You need two key pairs:
Partner credentials (issued once per integration)
PartnerIdandPartnerKeyare provided by Netvisor customer service when your integration is registered. They identify your software.
User credentials (issued by each end-customer, per company)
- Inside Netvisor, the customer opens Company menu → API identifiers → Create new api identifier. The generated
UserIdandUserKeyidentify the user/company your integration is acting on behalf of. - The customer must also grant your integration access to the specific endpoints under Company menu → Interface resource access rights.
PartnerKey and UserKey are never transmitted directly — they only feed into the MAC computation (§3). Keep them secret.
2. Request headers
Every request carries these headers:
| Header | Required? | Value |
|---|---|---|
X-Netvisor-Authentication-MACHashCalculationAlgorithm |
always | HMACSHA256. This is the only supported algorithm — set it explicitly in every request. |
X-Netvisor-Authentication-Sender |
always | Free-form name identifying your integration (e.g. Acme CRM Connector 2.4). |
X-Netvisor-Authentication-PartnerId |
always | Your PartnerId. |
X-Netvisor-Authentication-CustomerId |
always | The end-customer's UserId. |
X-Netvisor-Authentication-Timestamp |
always | Request time as a string, conventionally dd.M.yyyy HH:mm:ss. See note below. |
X-Netvisor-Authentication-TimestampUnix |
always | Unix seconds since 1970-01-01 UTC. |
X-Netvisor-Authentication-TransactionId |
always | Unique GUID per request (replay-protection token; see §6). Reusing one returns REQUEST_NOT_UNIQUE. |
X-Netvisor-Interface-Language |
always | FI (Finnish), EN (English), or SE (Swedish). Selects the language of error messages and translations. If the header is omitted, errors return in Finnish. If the header carries an unrecognised value, the server falls back to English. |
X-Netvisor-Organisation-ID |
always | Business ID (Y-tunnus) of the target company. |
X-Netvisor-Authentication-MAC |
always | The computed signature (see §3). |
Note on
Timestamp. Every official Netvisor SDK emits thedd.M.yyyy HH:mm:ssformat. The server treats the value as an opaque string; onlyTimestampUnixis validated for freshness.
Header values containing spaces. Netvisor treats a
+in a header value as a literal+— it is not decoded to a space. Compute the MAC over the decoded value of each header: a literal space and%20both decode to a space, while a literal+stays+.
Optional:
| Header | Purpose |
|---|---|
X-Netvisor-Authentication-UseHTTPResponseStatusCodes |
Set to 1 to opt into real HTTP status codes on failure (400/401/403/410) instead of the default 200 + FAILED body. Strongly recommended for new integrations. Note: a 500 may be returned regardless of this flag on fatal server errors. |
3. Computing the MAC (HMACSHA256)
Build the message as 10 values joined with literal & (no spaces), in this exact order:
URL & Sender & UserId & Timestamp & Language & OrganisationId & TransactionId & TimestampUnix & UserKey & PartnerKeyImportant details:
- URL is the decoded request URL the server will see after URL-decoding, including protocol, host, port (if non-default), path, and full query string. Strip the fragment (
#…) if any.- Example URL value:
https://isvapi.netvisor.fi/getsalesinvoice.nv?netvisorkey=42 +in the query string is preserved as a literal+, not decoded to a space. The server explicitly substitutes+→%2Bbefore URL-decoding so the literal stays in place — your MAC computation must do the same.- The host portion is the public endpoint your integration normally targets (e.g.
https://isvapi.netvisor.fi). Do not vary the trailing slash from what your client actually sends.
- Example URL value:
- Encoding. The entire message string is encoded as ISO-8859-15 bytes before being fed into the hash. The HMAC key is encoded as UTF-8 — for the all-ASCII keys Netvisor issues, the two encodings are equivalent.
- The last two
&-separated fields of the message string are character-for-character identical to the HMAC key string. This duplication is intentional: the private keys appear inside the message and as the HMAC key. They never travel as headers.
Compute the signature as HMAC-SHA256 with:
- Key:
UserKey & PartnerKey(the two private keys joined with one&character). - Message: the concatenation above.
Send the hex digest in the X-Netvisor-Authentication-MAC header. Case is not significant — the server compares case-insensitively, but every official Netvisor SDK emits uppercase, so prefer uppercase to avoid surprises when diffing against captured traffic.
Reference pseudo-code:
privateKeys = userKey + "&" + partnerKey
message = url + "&" + sender + "&" + userId + "&" + timestamp
+ "&" + language + "&" + organisationId + "&" + transactionId
+ "&" + timestampUnix + "&" + privateKeys
mac = hmac_sha256(key = privateKeys, message = message).hex()Worked example
Given:
URL = https://isvapi.netvisor.fi/getsalesinvoice.nv?netvisorkey=42
Sender = Acme CRM Connector 2.4
UserId = 12345
Timestamp = 13.5.2026 09:42:11
Language = EN
OrganisationId = 1234567-8
TransactionId = 60a2b1e2-1f4c-4e5a-9b2e-3c4d5e6f7a8b
TimestampUnix = 1746085331
UserKey = USER_PRIVATE_KEY_VALUE
PartnerKey = PARTNER_PRIVATE_KEY_VALUEThe message string fed into HMAC-SHA256 is:
https://isvapi.netvisor.fi/getsalesinvoice.nv?netvisorkey=42&Acme CRM Connector 2.4&12345&13.5.2026 09:42:11&EN&1234567-8&60a2b1e2-1f4c-4e5a-9b2e-3c4d5e6f7a8b&1746085331&USER_PRIVATE_KEY_VALUE&PARTNER_PRIVATE_KEY_VALUEThe HMAC key is USER_PRIVATE_KEY_VALUE&PARTNER_PRIVATE_KEY_VALUE. The resulting hex digest goes into X-Netvisor-Authentication-MAC.
4. Response format
All responses are XML wrapped in a <Root> envelope:
<Root>
<ResponseStatus>
<Status>OK</Status>
<TimeStamp>20.4.2026 18:01:25</TimeStamp>
</ResponseStatus>
<!-- operation-specific payload -->
</Root>
About
<TimeStamp>in responses. Local time (Europe/Helsinki), not UTC and not ISO 8601 — for example20.4.2026 18:01:25.
On success, <ResponseStatus> contains exactly one <Status>OK</Status> and the <TimeStamp>; the operation-specific payload appears as a sibling of <ResponseStatus> under <Root>.
On failure, <ResponseStatus> carries two <Status> elements — the first is the literal token FAILED, the second is one of the documented error categories optionally followed by :: <detail>:
<Root>
<ResponseStatus>
<Status>FAILED</Status>
<Status>INVALID_DATA :: Customer identifier is required.</Status>
<TimeStamp>20.4.2026 18:01:25</TimeStamp>
</ResponseStatus>
</Root>
Not every category includes a :: detail suffix. In particular, AUTHENTICATION_FAILED is returned without a detail message for security reasons — diagnose those failures against your local request timestamp and the headers you sent, not the response body.
Each operation's 200 response is modelled with oneOf over <success> / ErrorResponse. Inspect ResponseStatus.Status[0] to discriminate: OK selects the operation-specific success schema; FAILED selects ErrorResponse, whose description enumerates every category your integration may receive.
5. HTTP status codes (opt-in)
By default, every request returns 200 OK, regardless of business outcome — the real status lives inside <ResponseStatus>. Set X-Netvisor-Authentication-UseHTTPResponseStatusCodes: 1 to opt into a more conventional mapping:
| HTTP | Meaning |
|---|---|
200 |
Success. |
400 |
Invalid data / malformed input. |
401 |
Authentication failed (MAC mismatch, expired keys, missing headers). |
403 |
The partner does not have access to this resource for the target company. |
410 |
The target company has been suspended or terminated. |
500 Internal Server Error may be returned regardless of this opt-in on fatal server-side errors — clients should always be ready for it.
404 Not Found is not part of this mapping. A request to an unknown endpoint path returns a 404 with a response body that is not the XML envelope and will not match any schema in this specification.
The response body shape is unchanged; only the HTTP status line differs. Per-operation responses in this specification only list 200 because that is the default mode. If you opt into HTTP status codes, your generated client will need to handle 400 / 401 / 403 / 410 (and unconditionally 500) manually — these are not enumerated per-operation.
6. Replay protection (TransactionId)
X-Netvisor-Authentication-TransactionId is a unique-per-request identifier (typically a GUID). A duplicate value is rejected with REQUEST_NOT_UNIQUE — this is replay protection, not Stripe-style idempotency, so the original response is not replayed. Use a fresh TransactionId for every retry that you genuinely want re-processed.
This specification is auto-generated from the Netvisor public API source code.
Production
Demo
Partner ID issued by Netvisor customer service when the integration is registered. Identifies the software, not the end-customer.
| Key | In | |
|---|---|---|
| X | Header |
Message Authentication Code for the request, computed with the HMACSHA256 algorithm: HMAC-SHA256 with key = (UserKey & '&' & PartnerKey), message = (URL & Sender & UserId & Timestamp & Language & OrganisationId & TransactionId & TimestampUnix & UserKey & PartnerKey), lowercase hex digest. See the spec description for the full algorithm.
| Key | In | |
|---|---|---|
| X | Header |
End-customer's UserId (the user-id half of the API identifier the customer generates inside Netvisor under Company menu → API identifiers). Required for all data operations.
| Key | In | |
|---|---|---|
| X | Header |
Sales
Customers, sales orders, sales invoices, sales payments, and sales-side master data.
Purchases
Vendors, purchase orders, purchase invoices, outgoing bank transfers, and purchase-side master data.
Products
Product master data, web-shop product publishing, warehouse inventory, and stock events.
Travel
Travel expense reports and supporting attachments.
Accounting
General-ledger postings, account chart, voucher types, dimensions, budgets, and accounting periods.
Working Time
Working-hour entries, record types, and working-time corrections.
Salaries
Employees, payroll paycheck batches, salary parameters, payslips, settlement points, and salary obligations.
Document Scan
Imports an e-scan document.
User Management And User Invitation
Manage the users of a Netvisor company: send, verify, list and cancel user invitations, and view, edit, change the validity of or remove users' access rights.