Spiris is one of Sweden's largest cloud accounting platforms for small and medium-sized businesses. If you are building software for the Swedish market, you will almost certainly encounter it. But before writing a single line of integration code, there is a naming problem worth understanding.
Spiris, Visma eAccounting, Visma eEkonomi: What Each Name Means
In 2025, Visma Spcs rebranded to Spiris. In Sweden, the product previously called Visma eEkonomi became Bokföring & Fakturering (Bookkeeping & Invoicing in English). In all other markets, the same product still goes by eAccounting. The company was founded in 1984 and has several hundred thousand customers, making it one of Sweden's leading platforms for financial management.
Visma eAccounting runs under different names across markets: eAccounting in Norway and the Netherlands, Bokföring & Fakturering via Spiris in Sweden, and ePasseli in Finland. These are not different products. They share the same underlying API at eaccountingapi.vismaonline.com. If a customer tells you they use Visma eEkonomi, Visma Spcs, or Spiris, they are all pointing to the same integration target.
One distinction worth flagging: Visma Administration (also known as Visma SPCS Administration) is a separate, on-premise desktop accounting product that does not share this API. If a customer is running Visma Administration, that is a different integration entirely.
Spiris API Endpoints: What You Can Read and Write
The Spiris API is REST-based and covers the core accounting data models you would expect from an SME accounting platform. The base URL for all requests is https://eaccountingapi.vismaonline.com/v2/. Through the API you can read and write customers and suppliers, sales and purchase invoices, journal entries, VAT codes, articles and products, and fiscal period data.
To fetch a list of customers:
curl "https://eaccountingapi.vismaonline.com/v2/customers" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
A successful response returns a Data array alongside pagination metadata:
{
"Data": [
{
"Id": "3e8f2a1b-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"Name": "Acme AB",
"VatNumber": "SE556677889001",
"EmailAddress": "billing@acme.se",
"IsPrivatePerson": false
}
],
"Meta": {
"TotalNumberOfResults": 143,
"CurrentPage": 1
}
}
Before writing invoices or journal entries, you need to resolve the VAT codes available in the tenant's account. Each tenant may have a different set depending on their market and configuration:
curl "https://eaccountingapi.vismaonline.com/v2/vat-codes" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
For a Swedish company, the response will include the three Moms rates:
{
"Data": [
{ "Id": "MP1", "Name": "Moms 25%", "VatPercent": 25.0 },
{ "Id": "MP2", "Name": "Moms 12%", "VatPercent": 12.0 },
{ "Id": "MP3", "Name": "Moms 6%", "VatPercent": 6.0 }
]
}
These Id values (MP1, MP2, MP3) are what you reference in invoice rows. Dutch and Norwegian tenants will return different VAT code IDs, so never hardcode them.
Creating a Sales Invoice
Creating a sales invoice requires a CustomerId (the GUID from the customer record), a valid VatPercent that matches a code in the tenant's account, and a date in ISO 8601 format. A minimal invoice creation request looks like this:
curl -X POST "https://eaccountingapi.vismaonline.com/v2/customerinvoices" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"CustomerId": "3e8f2a1b-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"InvoiceDate": "2026-04-23",
"DueDate": "2026-05-23",
"YourReference": "PO-1234",
"Rows": [
{
"Text": "Software license Q2 2026",
"Quantity": 1,
"UnitPrice": 1200.00,
"VatPercent": 25
}
]
}'
For Swedish invoices involving ROT or RUT deductions, the invoice row requires three additional fields: TypeOfVatFreeReduction (ROT or RUT), HousingPropertyDesignation (the property reference), and ReducedInvoicedAmount (the deduction amount). Missing any of these on a ROT/RUT invoice will cause a validation error.
To read journal entries for a specific date range:
curl "https://eaccountingapi.vismaonline.com/v2/journal/entries?fromDate=2026-01-01&toDate=2026-03-31" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
The Spiris Payroll API
The Spiris developer portal also exposes a Payroll API alongside the accounting one, with its own dedicated API reference at developer.vismaonline.com. Both APIs share the same OAuth identity server at identity.vismaonline.com, which means the same access token covers both as long as the payroll-specific scopes are included in the authorization request your customer approves.
For products that need to read salary data, payroll runs, or employee records alongside invoicing and accounting data, this matters: you can build a single connect flow that requests both accounting and payroll scopes, rather than asking your customers to authorize twice. The trade-off is that requesting a wider scope set upfront increases the permissions your app is asking for during onboarding, which is worth thinking about from a conversion perspective.
Authentication and OAuth 2.0 Scopes
Applications connect to the Spiris/eAccounting API using OAuth 2.0. The flow is initiated by a user clicking a connect button in your application, and the result is a token your application uses to access protected resources on behalf of that user.
The authorization request directs your customer to the Visma identity server:
https://identity.vismaonline.com/connect/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&response_type=code
&scope=ea:sales ea:purchase ea:accounting offline_access
&state=RANDOM_STATE_VALUE
Once the user approves and you receive the authorization code, exchange it for tokens:
curl -X POST "https://identity.vismaonline.com/connect/token" \
-H "Authorization: Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=AUTH_CODE&redirect_uri=YOUR_REDIRECT_URI"
The response includes an access token (valid for 3600 seconds) and a refresh token:
{
"access_token": "eyJ...",
"expires_in": 3600,
"token_type": "Bearer",
"refresh_token": "abc123..."
}
The BASE64_ENCODED_CLIENT_ID_AND_SECRET in the Authorization header is base64(client_id:client_secret). Store the refresh token per tenant. When the access token expires, exchange the refresh token for a new one:
curl -X POST "https://identity.vismaonline.com/connect/token" \
-H "Authorization: Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=STORED_REFRESH_TOKEN"
The per-resource scope model is where most teams get stuck. Every resource area has its own scope: ea:sales for sales invoices, ea:purchase for purchase invoices, ea:accounting for journal entries and accounts. Missing a scope in the authorization request produces authorization errors on those endpoints rather than empty results, and the only fix is to have your customer re-authorize. Include offline_access to receive a refresh token at all.
From the end-user's perspective, the connect flow ends at a scope approval screen on identity.vismaonline.com. That screen lists every scope your application has requested. Scopes that look overly broad create drop-off, so request only what your integration actually needs.
Pagination and Rate Limits
Collection endpoints return 50 results per page by default. For any customer with more than 50 records on an endpoint, requests without explicit pagination will silently ignore everything after the first page. To paginate correctly, pass page and limit as query parameters:
curl "https://eaccountingapi.vismaonline.com/v2/customerinvoices?page=2&limit=100" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
The Meta object in the response tells you the total record count so you can calculate how many pages to fetch:
{
"Meta": {
"TotalNumberOfResults": 312,
"CurrentPage": 2
}
}
With 312 invoices and a limit of 100, that is four requests (pages 1 through 4) to retrieve all records. Build this loop into every collection sync from the start rather than adding it later when a customer complains about missing data.
The rate limit is 600 requests per minute per client and endpoint. When you exceed it, the API returns:
{
"ErrorCode": 4010,
"DeveloperErrorMessage": "API calls quota exceeded! maximum admitted 600 per Minute. Try again in 55 seconds."
}
Batch reads where possible. Fetching 100 records per page instead of 50 halves the number of requests for a full sync.
Sweden-Specific Requirements: BAS Accounts, Moms VAT, and ROT/RUT
This is where the Swedish implementation diverges from eAccounting in Norway and the Netherlands, and where assumptions built on other markets will fail.
Swedish companies use the BAS chart of accounts (BAS-kontoplanen). Account numbers follow BAS conventions and differ structurally from Dutch or Norwegian account setups. Before writing any journal entries, retrieve the tenant's chart of accounts to confirm the account numbers you need exist:
curl "https://eaccountingapi.vismaonline.com/v2/accounts" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Swedish VAT is called Moms and has three rates: 25%, 12%, and 6%, each mapping to specific VatCodes in the API, with reporting obligations to Skatteverket. Always fetch VAT codes dynamically rather than hardcoding them, since code IDs vary across tenants and markets.
ROT and RUT deductions require additional fields on invoice rows. The invoice creation example above shows the base structure. For a ROT invoice on a construction job, the row would also include:
{
"Text": "Roof repair labour",
"Quantity": 8,
"UnitPrice": 650.00,
"VatPercent": 25,
"TypeOfVatFreeReduction": "ROT",
"HousingPropertyDesignation": "STOCKHOLM VASASTADEN 1:23",
"ReducedInvoicedAmount": 2600.00
}
These fields are Sweden-only. The Norwegian and Dutch eAccounting API will reject invoice rows that include them.
Getting Started with the Spiris Partner Programme
To make authorized requests, you register as a partner on the Visma Developer Portal at developer.vismaonline.com. Registration gives you a client ID, client secret, redirect URI registration, and access to a sandbox environment that includes a test company. Spending time in the sandbox creating invoices and suppliers before writing production code pays off. It gives you a concrete picture of what your customers' data actually looks like before you design your data mapping.
Registering as a partner does more than unlock API access. Once your integration is reviewed and approved, it can be listed in the Spiris partner marketplace, which is visible to Spiris customers browsing for integrations from inside the platform. For software companies targeting the Swedish SME market, this is a meaningful distribution channel: your product appears in front of users who are actively looking for tools that connect to their accounting system. It is worth factoring into your go-to-market plan alongside the technical work.
What Building a Spiris Integration Actually Costs
Building a direct Spiris integration means managing per-resource OAuth scopes, handling 60-minute token expiry with silent refresh across every connected tenant, writing pagination for every collection endpoint, resolving tenant-specific account and VAT code references before any write operation, and handling Swedish invoice fields for ROT/RUT. That is before error handling, retry logic, and ongoing maintenance as the API evolves.
For most companies building in the Nordic market, Spiris is also one of several accounting platforms you need. Adding eAccounting for Norwegian customers or ePasseli for Finnish ones means repeating most of this across separate integrations.
Apideck's unified accounting API covers the broader Visma eAccounting family and other Nordic and European accounting platforms through a single integration. Normalized data models, managed OAuth flows, and pagination handling come with each connector.
Note: Apideck's Spiris connector is currently in development. Sign up for early access to be notified when it launches.
FAQ: Spiris and Visma eAccounting API
Is Spiris the same as Visma eAccounting?
Yes. Spiris is the rebranded name for Visma Spcs, the company that develops and maintains the eAccounting product in Sweden. In Sweden the product is now called Bokföring & Fakturering. In Norway and the Netherlands it is still called eAccounting. All versions share the same API at eaccountingapi.vismaonline.com.
What happened to Visma eEkonomi? Visma eEkonomi was the Swedish-market name for the product before the 2025 rebrand. It is now called Bokföring & Fakturering under the Spiris brand. The API is unchanged — no code updates are needed if you were already integrated.
What is the difference between Spiris and Visma Administration? Visma Administration is a separate on-premise desktop accounting product. It does not use the same API as Spiris/eAccounting. If your customer uses Visma Administration, that requires a different integration approach.
Does the Spiris API work for Norwegian and Dutch customers too? Yes. The same API endpoint covers eAccounting in Norway and the Netherlands. The authentication flow, rate limits, and pagination model are identical across markets. The main differences are country-specific data: VAT codes, chart of accounts structure, and invoice fields vary by market.
Does Spiris have a Payroll API? Yes. The Payroll API is available through the same Visma Developer Portal and shares the same OAuth identity server as the accounting API. If your application needs payroll data alongside accounting data, you can request both scope sets in a single authorization flow.
Where do I register to get API access to Spiris? At developer.vismaonline.com under the Spiris Partner Programme. You receive a client ID, client secret, redirect URI registration, and sandbox access on signup.
Ready to get started?
Scale your integration strategy and deliver the integrations your customers need in record time.








