Skip to main content
Sign in with HEVN is how a client comes to exist. Your customer signs in with Google in a HEVN-hosted popup on your site, allows your product to act on the account, and your backend exchanges the code that comes back for a cl_… id. The same popup is where the account holder later approves each payout you book for them. The window takes nothing from your page but the session URL your server got from HEVN. It shows no HEVN product screens: a sign-in, one consent screen, and, for a payout, the terms being approved.

Before you start

  • Your integrator account is active. HEVN switches it on. Until it does, POST /dapi/v1/connect/sessions and POST /dapi/v1/clients/link answer 403 client_creation_not_enabled — see Going live.
  • Your site is an allowed origin. In the HEVN app, open Settings → Partner program → Developer and find the Sign-in window card. Add every origin your callback page is served from under Allowed sites. A session for any other redirectUri is refused.
  • You have a callback page. One static page on an allowed origin that hands the popup’s result back to the page that opened it. It is shown below.

Configure the window

The Sign-in window card holds everything about how the popup looks and where it may return. Nothing about the window is configurable from the API or from the session URL: a page that opens the popup cannot restyle it, retitle it or redirect it. The card shows a preview of the consent screen as you edit. Removing an allowed site also stops every session already issued for it: the window refuses to open a session whose redirectUri is no longer on the list.

1. Open the popup inside the click

Browsers block a popup that is not opened synchronously by a user gesture. Open an empty window first, inside the click handler and before any await, then ask your server for the session and point the window at it.
Browser

2. Create a session on your server

POST /dapi/v1/connect/sessions is called with your own access token and no X-Hevn-Account — it is about your integrator account, so the header answers 400 account_scope_conflict.
Response — 201
string
required
link asks the account holder to connect their account. sign asks them to approve one payout — see Approve a payout.
string
required
The page the window returns to. An https:// URL — or http://localhost and http://127.0.0.1 in development — with no fragment, on an origin listed under Allowed sites. Any other origin answers 403 redirect_uri_not_allowed.
string
The po_… to approve. Required for sign, refused for link.
url opens the window and lives for about ten minutes, until expiresAt. HEVN signs it, and it is bound to your integrator account, the action, the payout, the redirectUri and a one-time nonce. state is that nonce: the window sends it back on redirectUri with the result, and nothing else ties the result to this session. Give url to the browser and keep state on your side.

3. Bind the session to this browser

Never let the browser tell your server which client it is. Remember state in an HttpOnly cookie when you create the session, and accept a code only when the browser returns the same state in that same cookie jar. A code arriving with no cookie, or with another state, came from somewhere else.
Node

4. Exchange the code

The window returns a code that lives for five minutes and works only for your integrator account. Exchange it server-side, again with no X-Hevn-Account:
Response — 200
The answer is the client record. Store id against your own user. From now on your server finds the client from its own session and sends that id in X-Hevn-Account; the browser never carries it, so no page can ask your server to act for somebody else’s account. Exchanging the same code again returns the same client.

The callback page

The window finishes by navigating to redirectUri with the result in the query string: code or error for a link, status, payout and reference or error for a payout, and state on every one. The callback page posts that query to the page that opened the popup over a BroadcastChannel, then closes the window.
callback.html
The opener listens on the same channel and settles only on the result that carries its own session’s state:
Browser
The result does not travel through window.opener. Google’s sign-in cuts the popup off from the page that opened it, so by the time the window returns, window.opener is null. A BroadcastChannel reaches every page of your origin in the same browser, which is why the callback page must live on the same origin as the page that opened the popup. state on the result is the nonce inside the session token, and it equals the state field POST /dapi/v1/connect/sessions answered. The browser check only routes the result to the right page; the check that matters is your server’s, against its cookie.
The Node reference at hevn-inc/dapi-sdk ships this browser half as HevnConnect: HevnConnect.open() opens the popup synchronously in the click handler, .link(url), .sign(url) and .run(url) navigate it and resolve with the result, and HevnConnect.complete() is the whole callback page. Like the rest of that repository, it is a working reference to read, not a supported package.

Who can be linked

Only an account created in the sign-in window can be linked. The window signs out any HEVN session in that browser before every link sign-in, so the holder always chooses the Google account explicitly, and: The consent screen names your product — the Title you configured, or your account’s name — and the origin of redirectUri, and says what you get: you can see balances, open accounts and prepare transfers, and the holder approves every transfer themselves in this window.

Approve a payout

A payout you book for a linked client answers authorization: "client" and carries no approval for your key. The holder signs it. Create a sign session for that payout and open the popup exactly as for a link:
The payout must belong to a client linked to you and still be awaitingSignature. Otherwise the session is refused with 404 payout_not_found or 409 payout_not_awaiting_signature. In the window the holder signs in — a HEVN session already open in that browser is reused for sign — sees the amount, the contact’s name and who requested it, and their own wallet signs the debit. The callback receives status=submitted, payout=po_… and, when the debit was sent, reference. A payout that was no longer waiting by the time the window opened comes back with its current status and nothing signed. The redirect is a hint, never the record. Read GET /dapi/v1/payouts/{payoutId} with the client in X-Hevn-Account and follow it to settled like any other payout — see Payouts.

Errors

Refusals come from two places. Your server sees the API’s; your callback page sees the window’s, as error on the redirect. A session that is invalid or already expired when the window opens never reaches your callback: the window shows This link has expired or is invalid and sends nothing back. Give up on the opener side once expiresAt has passed, and close the popup.

Next: Clients

Read the linked client, wait for it to be ready, and keep the one id that identifies it.