How hosted flows such as onboarding work, and how the end user comes back to you.
Some things cannot happen in an API call, because they need a person: signing a contract, identifying with BankID, answering KYC questions. Invoier hosts those flows. A session is how you start one for an end user.
You do not build any of the screens. You create a session, send the end user to its url, and take them back when they are done.
Session types
| Type | Used for |
|---|---|
ACCOUNT_ONBOARDING | Onboarding a new client. The end user signs the contract and completes KYC. |
ACCOUNT_KYC_RENEWAL | Renewing KYC for an account that is already onboarded. |
The short forms ONBOARDING and KYC_RENEWAL are accepted and mean the same. They are created on an account with POST /accounts/{accountId}/sessions.
An account can have one onboarding session at a time. Creating it again while it exists returns the existing session (200 instead of 201), so it is safe to call whenever your end user clicks "Start".
The life of a session
- You create the session. It is
CREATEDand itsurlis ready to hand to the end user. - The flow is prepared with the signing provider, which is called provisioning. In production this starts when the end user first opens the
url. The session isPROVISIONINGfor a few seconds, during which the end user waits, or is sent to youronProvisioningcallback if you registered one. It then becomesREADY. In the sandbox there is no real signing provider, so provisioning starts as soon as the session has been created. - The session gets an
expiresAtwhen provisioning is done. By default it lasts 7 days. The end user is then in the flow and the session isACTIVE. - They finish, cancel or fail. The session becomes
COMPLETEDorCANCELED, and the user is redirected to the matching callback. - For onboarding, the account then moves on, see How it works.
See the diagram in How it works for all the statuses.
The url
The url is for the end user's browser. You can send it as soon as you have created the session, because in production the session is provisioned when it is opened, and you do not have to wait for READY. Redirect them to it or put it in a link or a button. It is tied to the session, so do not share it with anyone else, and do not call it from your server.
It starts the flow. When the flow is over, the browser is sent on to one of your callbacks.
Callbacks
Callbacks are redirects, not webhooksInvoier does not call your server when a session changes. Callbacks send the end user's browser to a url that you chose. Nothing is sent in a request body, there are no retries and nothing is signed. Webhooks are planned, but they do not exist yet.
You register callbacks when you create the session:
{
"session": {
"sessionType": "ACCOUNT_ONBOARDING",
"callbacks": {
"onComplete": { "url": "https://app.example.com/onboarding/done?org=$ORG_NUMBER" },
"onCancel": { "url": "https://app.example.com/onboarding/cancelled" },
"onError": { "url": "https://app.example.com/onboarding/failed?message=$MESSAGE" }
}
}
}onCancel, onComplete and onError are required. onProvisioning is optional. You can change callbacks later with POST /sessions/{sessionId}.
| Callback | The end user arrives here when |
|---|---|
onComplete | they finished the flow |
onCancel | they cancelled. They can open the session url again |
onError | something went wrong. The reason is available as $MESSAGE |
onProvisioning | they opened the url before the session was ready. Optional |
Tokens
Tokens are replaced when the end user is redirected. In the path of the url a token is replaced wherever it appears, as in /done/$ORG_NUMBER. In the query string a token is only replaced when it is the whole value of a parameter, as in ?org=$ORG_NUMBER. A token inside a longer value, like ?a=x$LOCALE, is left as it is. Only the tokens listed for a callback can be used in it, and unknown tokens are rejected when you create the session.
| Token | Value | Available in |
|---|---|---|
$LOCALE | the language of the flow, such as sv-SE | all callbacks |
$URL | the session url | onCancel, onProvisioning |
$MESSAGE | a technical description of what went wrong, meant for your logs rather than for the end user | onError |
$ORG_NUMBER | the organisation number of the company | onComplete |
$COUNTRY | the country of the company | onComplete |
$EXPORTS_URL | where to fetch the result of the session | onComplete |
$URL is how a "Try again" button on your cancel page can send the end user back into the flow.
What to do when the user arrives
A callback only tells you where the end user went. Treat it as a cue to show the right screen, not as proof of anything, because anyone can open a url. To find out what really happened, fetch the session or the account and read the status.
You are in charge of the loop. Make sure the callback pages end somewhere useful:
onComplete: show progress, and poll the account until it isENABLED. Do not send the user back to the sessionurl.onCancel: offer to try again with$URL, or to leave.onError: show a general error, log$MESSAGE, and offer to start over. If you create a new session each time, you can end up with several. Check the existing one first.
Parameters
parameters configure the flow. locale is sv-SE (the default) or en-US. Some parameters are only available when Invoier has enabled them for your key: expirationInDays, deferProvisioning. Asking for one that is not enabled is a 400.
Parameters cannot be changed after the session has been provisioned.
Pre-filling the KYC form
If you already asked your client the KYC questions, send the answers as parameters and the end user can skip the form. See Pre-filling the KYC form.
Updating and deleting
POST /sessions/{sessionId}updates callbacks and metadata. Sessions that are completed, expired, failed or deleted cannot be updated. Send thelastModifiedAtyou last read, and you get a412if it changed in the meantime.DELETE /sessions/{sessionId}deletes a session that has not started. For sessions that areREADY,ACTIVEorCANCELED, add?force=true. Forcing needs a role that Invoier gives you.
Expiry
A session that is not completed expires at expiresAt. An expired session cannot be used, but you can create a new one for the same account.
