maesn
Product insight

Every auth method, one unified authentication flow

Maesn abstracts OAuth 2.0, OAuth 2.1, API keys and 2FA behind a single flow, and handles multi-company setups, automated token refresh, headless integration and signed callbacks, so you implement authentication once instead of once per target system.

Every method, one flowX-ACCOUNT-KEY
OAuth 2.0redirect and consent
API keyentered or sent headless
OAuth 2.1PKCE, and systems keep moving to it
2FAsecond factor required
maesn authenticates
One account key per customer
{ "accountKey": "<account-key>" }
Trusted by winning software teams
HubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinHEROHolviLanes & PlanesAgicapHubSpotTipaltiPaywiseRallyQredNordhealthFindityFintoClockinHEROHolviLanes & PlanesAgicap
The concept

What is unified authentication

Before you can read or write a single record, every customer has to connect their system, and every ERP or accounting platform authenticates differently. One uses OAuth with a redirect screen, the next wants an API key pasted into a form, another asks for a username and password or a second factor, and some make the customer pick a specific company before anything works at all. And a shared standard does not save you: OAuth 2.0 is specified, yet every system implements it slightly differently, quirks and documentation gaps included, so three OAuth systems still tend to cost three implementations. Building and maintaining a separate login for each one is where integration projects lose their first weeks.

Unified authentication puts one flow in front of all of it. You ask Maesn for an authentication URL and name the target system, you send the customer to that URL, and they come back to a redirect you control with one account key attached. The method, the number of steps and the company selection all stay on Maesn's side, so your integration authenticates the same way whichever system your customer runs. This is also the one place in the whole unified API where you name the system at all: afterwards the account key carries that context, and every later call looks identical whatever is behind it.

It is the entry point to the rest of the Unified API. The same two headers that authorise a connection authorise every call you make afterwards, so once a customer is connected you read and write their data through one standardised set of endpoints and one common data model, whichever system sits behind it.

The problem

Every system logs in differently

The same task, connecting a customer, looks different in every system: a different auth method, a different number of steps, a different token lifetime and a different place you have to build the UI.

Auth method
OAuth 2.0OAuth 2.1API key2FA
Company selection
single tenantpick a companycompany plus environment
Token lifetime
long-livedrefresh requiredshort-lived
Where you build it
redirect UIkey-entry formheadless

All of that is the half that happens once a vendor has let you in. Which of them lets you in at all is decided before any of it, by an API key you can generate yourself at one end of the market and a commercial partnership with a review process at the other, and how access is granted in this market sets out what each route costs in time rather than in code.

How Maesn handles it

Two keys, one flow

You authenticate against Maesn, not against each system. Two headers carry every request, and one endpoint runs the customer's login for you.

X-API-KEY
Identifies your platform

The key you get when you sign up with Maesn. It authenticates every request as coming from your platform, whichever customer that request is for.

X-ACCOUNT-KEY
Identifies one customer

Issued once a customer authenticates, unique to that customer and target system. A customer can hold several of these, one per connected system.

Every method, abstracted

OAuth 2.0, OAuth 2.1, API keys and 2FA are all handled behind one flow, so you never implement a system's login by hand.

Multi-company built in

Where a system needs the customer to pick a company or environment, that step is embedded in the same flow and stored for later requests.

Hosted or headless

Maesn's connect page takes your colours, your logo, your wording and one entry per language, or you run a fully headless flow and build the UI yourself.

Signed callbacks

Verify that a callback genuinely came from Maesn with an HMAC-SHA256 signature, and receive the account key in the body instead of the URL.

authenticate.sh
GET /auth/datev-uo
?environmentSelection=true
&callbackUrl=https://your-app.com/callback
 
x-api-key: YOUR_API_KEY
Interactive Authentication

Multi-company, one click for the customer

Some systems will not let a customer connect until they choose a specific company or environment, and reaching that choice can take several authentication steps. DATEV is the clearest case: the customer authenticates once with a short-lived token, sees the list of companies they have access to, selects one and then authenticates a second time for that company, which is the step that returns the long-lived token the integration actually runs on. Business Central adds a second dimension on top: each company can also have its own environments, a production and a test one, so the choice is not one list but two.

Maesn embeds all of it in a single flow. Set environmentSelection=true and the customer is shown a selection page, picks their company and is redirected back into your app with one account key. The stored selection is reused on every later request, so you never send a company identifier by hand, and you never build the selection step yourself. Whether or not a given system needs a choice, your integration triggers the same one authentication.

What DATEV actually requires
1Authenticate once, short-lived token
2Fetch the list of companies
3Select one company
4Authenticate again for that company
maesn embeds the flow
One Maesn authentication

The customer clicks once, picks their company from an embedded list and lands back in your app. Every multi-step detail stays on Maesn's side.

environmentSelection=true
The connect page

Your colours on the page, your customer's language on it

Some systems need a step from the end user: a company to choose, an API key to paste. That page is Maesn's, and both how it looks and what it says are yours to set.

no localethe default
Connect your Lexware Office accountAPI keyFind your key under Settings, Integrations.ConnectCancel
locale: deone entry, merged in
Lexware Office verbindenAPI-SchlüsselDen Schlüssel findest du unter Einstellungen.VerbindenAbbrechen
What the customer sees
locale=deThe German entry, field by field.
locale=de, one field unsetThat one field comes from the default entry, the rest stays German.
locale=es, no entryThe whole default entry, because no Spanish texts were sent.
no texts sent at allThe built-in wording, which the reference names per field.

One call to the submission page style endpoint carries both halves. The colours are field by field rather than a theme, so the background, the input surfaces, the title, the body text, the validation errors and each of the two buttons are set independently, and a logo goes in as an SVG or a PNG. The wording travels in the same call as a list of entries, one per locale, each holding the headline, the free text between the fields and the buttons, and the two button labels.

Entries merge rather than replace, which is what makes this safe to extend. Sending German leaves every other language untouched, so adding a market is one call with one entry and not a full rewrite of your configuration. The entry without a locale is the default, and it is what a customer sees whenever the locale you asked for has no entry of its own, field by field rather than all or nothing. A field you never set falls back to the built-in wording, so there is no state in which the page renders empty.

It matters most where the connecting step is not a developer but a customer's bookkeeper, which is the normal case on a platform with hundreds of end users. HERO Software is the shape of that: tradespeople connecting their own DATEV, in their own language, from inside a product that is already in it. A page that changes language in the middle of that flow is the one moment the integration stops feeling like part of your product.

Signed callbacks

Trust the key that comes back

After a customer authenticates, the account key is delivered to your platform. Signed callbacks let you prove that delivery genuinely came from Maesn.

The callback your platform receives
https://your-app.com/callback?accountKey=…&ts=…&maesn_signature=…
accountKey
The key for the authenticated customer
ts
When the account key was created
maesn_signature
HMAC-SHA256 signature to verify
The check you run server-side
payload  = `accountKey=${accountKey}&ts=${ts}`
expected = hmacSha256(signingSecret, payload)
isValid  = expected === maesn_signature

Signatures match, so the callback came from Maesn. Callbacks older than your chosen window are rejected.

You generate a signing secret once for your tenant, and that is the only time it is returned, so it is stored on your side and nowhere else. Passing include_signature=true when you start authentication tells Maesn to sign the callback, and every callback then arrives with a timestamp and an HMAC-SHA256 signature you recompute against your secret. A signature that does not match, or a callback that is older than the window you allow, gets rejected before it reaches your logic.

The delivery itself is tiered too. Instead of a redirect that carries the account key in the query string, you can have Maesn deliver it in a request body or as a webhook event, so the key never lands in standard URL logging. If a secret is ever exposed, you rotate it by generating a new one, which invalidates the old secret immediately, so update your configuration before you rotate.

Why it matters

One flow, less to build and maintain

Building it yourself
  • Implement every auth method yourself
  • Build a company picker per system
  • Track token refresh and expiry
  • Rebuild the login for each new system
With Maesn
  • One flow for every auth method
  • Company selection embedded for you
  • Tokens refreshed and sequenced for you
  • New systems use the same flow

Authentication is rarely a one-time cost, and the expensive breaks are not the ones on your side. A system that moves from OAuth 2.0 to OAuth 2.1, which happens for good security reasons, does not simply change a parameter: the old consent stops being valid, and every connected customer has to go through authentication again. Behind Maesn that upgrade is absorbed. The Maesn authentication does not change, so the migration is not something you schedule, communicate to your customers or notice.

The smaller costs add up too. Tokens expire, systems change their login, and a burst of parallel traffic during a refresh can break the connection and force the customer to re-authenticate. Sending that burst through asynchronous processing releases it one request at a time, which is what stops a second refresh from starting while the first is still running. You build one authentication, and it keeps working as your customer base and the systems behind it change.

Some customers tell us this matters more to them than the unified data model itself. Their reason is consistent: authentication is where the time actually went. Not writing one flow, but working out per system which half of the documentation was current, why a token that should be valid was refused, and which undocumented quirk sat between a specification and a working login. It is the part of an integration that is easiest to underestimate before you have done it three times. Building it once is the reason product and engineering teams stop scheduling a login project per system.

Unified Authentication FAQ

Common questions

What does Maesn authentication abstract?

Every authentication method the target systems use: OAuth 2.0, OAuth 2.1, API keys and 2FA. It also handles the company or environment selection some systems require, so you implement one flow instead of one login per system.

What are the X-API-KEY and X-ACCOUNT-KEY headers?

X-API-KEY identifies your platform to Maesn and authenticates every request as coming from you. X-ACCOUNT-KEY is unique to each end customer and target system, issued once that customer authenticates, and authorises calls on their behalf. A customer can hold several account keys, one per connected system.

How does multi-company authentication work?

Through the Interactive Authentication Flow. Set environmentSelection=true and the customer is redirected to a selection page where they choose their company or environment. Those values are stored for future requests, so you never send them again. For DATEV, for example, the customer authenticates with a short-lived token, sees the list of companies, picks one and authenticates again for that company with a long-lived one, all embedded in one Maesn flow.

Can I build my own authentication UI?

Yes. For systems without an OAuth screen, Maesn provides a customisable page where the customer enters their credentials, or you can run a fully headless flow. The headless POST endpoint returns the account key directly in the response, so you can build the entire experience yourself.

Can I brand the page where my customer connects?

Yes, field by field rather than as a theme. The page background, the input and dropdown surfaces, the title colour, the body text, the validation error colour and both buttons are each set on their own through the submission page style endpoint, and your logo goes in as an SVG or a PNG. You can also set the headline, a free text between the fields and the buttons, and the labels on the submit and cancel buttons.

Can the connect page be shown in my customer's language?

Yes. The same call takes one entry per locale, each with its own headline, free text and button labels, identified by a BCP-47 tag such as de or de-DE. Entries merge rather than replace, so sending German leaves every other language untouched and adding a market is one call. The entry without a locale is the default and is used whenever the locale you requested has no entry, and a field you never set falls back to the built-in wording.

How do signed callbacks work?

You generate a tenant signing secret once, then pass include_signature=true when starting authentication. Your callback receives the account key, a timestamp and an HMAC-SHA256 signature you recompute server-side to confirm the request genuinely came from Maesn. The key can be delivered in a POST body or a webhook event rather than the URL, so it is not captured by standard URL logging.

Do I have to handle token refresh myself?

No. Maesn manages tokens on its side, and the one case that needs care is a burst sent in parallel: two requests can both find the token expired and the second can start a refresh while the first is running. Requests sent through asynchronous processing leave its queue one at a time, so that overlap cannot happen. Fired straight at a synchronous endpoint, the ordering is yours.

What happens when I add a new system?

The same flow covers it. Because you authenticate through Maesn rather than against each system directly, new integrations Maesn adds use the same endpoints and headers, with no new login code on your side.

How is the account key delivered back to me?

Two ways. The standard flow redirects the customer to your callback URL with the account key, or the Webhook Authentication Flow delivers the key to a webhook endpoint you specify as an event, signed so you can verify it.

Build once on the Unified API.

See how unified authentication works for your integration, or dive into the technical reference.