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)

  • PartnerId and PartnerKey are 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 UserId and UserKey identify 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 the dd.M.yyyy HH:mm:ss format. The server treats the value as an opaque string; only TimestampUnix is 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 %20 both 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 & PartnerKey

Important 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 + → %2B before 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.
  • 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_VALUE

The 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_VALUE

The 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 example 20.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.

Server
https://integration.netvisor.fi

Production

https://isvapi.netvisor.fi

Demo

Server Variables

Partner ID issued by Netvisor customer service when the integration is registered. Identifies the software, not the end-customer.

Fields
KeyIn
X-Netvisor-Authentication-PartnerIdHeader

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.

Fields
KeyIn
X-Netvisor-Authentication-MACHeader

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.

Fields
KeyIn
X-Netvisor-Authentication-CustomerIdHeader

Travel

Travel expense reports and supporting attachments.

Working Time

Working-hour entries, record types, and working-time corrections.

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.