Valverna

Authorization

Authorize a business

Access to a business's data is granted by its owner through an authorization-code flow. The owner approves your app on Valverna's consent page, you receive a short-lived code, and exchange it for a vlv_ access token.

How it works

1 Send the business owner to https://valverna.com/authorize with your client_id, redirect_uri, requested scope, and response_type=code.
2 The owner signs in, picks which of their businesses to grant, and reviews the requested scopes.
3 On approval, Valverna creates a grant and a single-use authorization code valid for 10 minutes, then redirects back to your redirect_uri with code and business_id.
4 Your server exchanges the code via POST /v1/authorize and receives a vlv_ access token. It is shown once — store it immediately.

The authorize URL

Standard authorization-code parameters. The consent page validates the redirect_uri origin against your app's registration and rejects unknown apps and unknown scopes.

Consent page URL

https://valverna.com/authorize
  ?client_id=cli_fortnox_sync
  &redirect_uri=https://yourapp.com/callback
  &scope=transactions.read+business.read
  &response_type=code
  &state=af0ifjsldkj

Parameters

client_id required
Your app's client id.
redirect_uri required
Where the owner is sent after approving or denying. Its origin must match your app's registered redirect URI.
scope required
Space-separated. Valid: transactions.read, business.read, transactions.write partners only — rejected for non-partner apps.
response_type required
Must be code.
state optional
Opaque value echoed back on the redirect. Use it to bind the callback to the user's session.

On approval

https://yourapp.com/callback?code=auth_8f3c2b91d4e7a605...&business_id=biz_9f3a2c81&state=af0ifjsldkj

On denial

https://yourapp.com/callback?error=access_denied&state=af0ifjsldkj

Exchange the code

POST /v1/authorize

Exchange the authorization code — an auth_-prefixed 64-character hex string — for an access token. Codes are single-use and expire 10 minutes after the owner approves — an expired or already-used code is rejected with 400 invalid_grant.

Request body

{
  "code": "auth_8f3c2b91d4e7a605..."
}

Response 200 OK

{
  "accessToken": "vlv_8b2c4f1e9a...",
  "tokenType": "Bearer",
  "businessId": "biz_9f3a2c81",
  "scopes": ["transactions.read", "business.read"]
}

Use the token in the Authorization: Bearer header for all subsequent requests — it is scoped to the single business in businessId.

Revocation

Tokens do not expire on their own. The business owner can revoke the grant at any time from their Apps & Access settings, after which every request with that token returns 401 access_revoked. Treat it as terminal: stop making requests and ask the owner to authorize again.