Sonela ISV guide · for software vendors

One key for every customer you serve

If you sell software to other businesses, you can put Sonela inside your product once. Your server says which customer each signed-in person belongs to, and Sonela answers that person from that customer's data and no one else's. A new customer needs nothing set up on our side: one platform key serves them all.

Before you start

  • A Sonela workspace. A platform key works on every plan, and counts as one key.
  • Data that already keeps your customers apart. Connect your database in the dashboard, say that several organisations share it, and name the column that says whose each row is: only tables that carry it are offered to the assistant. Or start from written material alone — manuals, help pages — which needs no column at all.

Your signing secret

In the dashboard, under Integration › Vouched sessions, create your signing secret. It starts sk_ and is shown once: keep it in your server's settings and never in a page. Creating a new one later keeps the old one working for 24 hours, so you can deploy it without an outage.

One platform key

Under Widget › Keys & snippet, create a key and switch on One key for every organisation my platform serves. Choose the data source and list the sites your product runs on; if each customer has a subdomain of its own, one entry such as https://*.yourapp.com covers them all. The key (pk_…) is public by design: it sits in your page source and opens nothing on its own.

Your server signs

For each signed-in person, a path on your own site — /api/sonela-voucher, say — answers {"visitorToken": "…"}: a token signed HS256 with your signing secret, carrying

  • aud: widget-vouch
  • exp: a few minutes out — Sonela refuses one more than 8 hours ahead
  • pk: your platform key
  • end_tenant: your id for the customer this person belongs to, one string or whole number of up to 128 characters
  • email, if you like: where the documents this person asks for are sent

Node, nothing to install

const crypto = require('node:crypto');

// Your signing secret (sk_...). It stays on your server.
const secret = process.env.SONELA_SIGNING_SECRET;
const publicKey = 'pk_...'; // your platform key

const base64url = (value) => Buffer.from(value).toString('base64url');

function sonelaToken(customerId) {
  const header = { alg: 'HS256', typ: 'JWT' };
  const payload = {
    aud: 'widget-vouch',
    exp: Math.floor(Date.now() / 1000) + 300, // five minutes
    pk: publicKey,
    end_tenant: customerId, // the customer this person belongs to
  };
  const signingInput =
    base64url(JSON.stringify(header)) + '.' +
    base64url(JSON.stringify(payload));
  const signature = crypto
    .createHmac('sha256', secret)
    .update(signingInput)
    .digest('base64url');
  return signingInput + '.' + signature;
}

// GET /api/sonela-voucher, behind your own sign-in:
//   response.json({ visitorToken: sonelaToken(signedInUser.customerId) });

The dashboard's Integration › Code for your site has the same signer in C#, Python and PHP, with the pk line filled in for the key you pick; set end_tenant to the signed-in person's customer.

A key made for one organisation needs the same two claims wherever its workspace requires bound vouchers, which every workspace created since that switch shipped does: end_tenant naming that key's organisation and pk naming the key, or the token is refused. One secret signs for every key you have, and those two claims are what keep a token for one customer off another's key.

One tag on your pages

The same tag for every customer

<script src="https://api.sonela.ai/sonela.js"
        data-key="pk_..."
        data-vouch-url="/api/sonela-voucher"
        defer></script>

Before each session the assistant asks that path for a fresh token, sending the person's own cookies, so the path must be on the same origin as the page. If your pages and your server live at different addresses, write the token into the tag as data-visitor-token when the page is rendered instead — that is how Sonela's own dashboard carries its help assistant.

Signing out

The assistant keeps its session in the page's memory and nothing on the device, so a sign-out that ends in a page load starts the next person afresh. A single-page app that signs out without one calls window.Sonela.destroy(), and when the next person signs in it adds the tag again with their token: the assistant starts afresh for them on the same page.

What Sonela holds to

  • The customer comes from your signed token alone, never from the page, and a platform key opens no session without one.
  • Every query is rewritten to that customer before it runs, and a platform key is refused on a data source that does not keep customers apart.
  • Sonela checks every open session against its key at each question: delete the key and every session it opened ends at its next one.
  • Each customer draws on a share of the rate limit of its own, so one busy customer cannot slow the rest. The month's question allowance is your workspace's, shared by all of them.
  • Of your API lookups, a customer's session is offered only those that name the customer, or that you marked as answering the same for everyone.
  • Usage lists each customer by the id you signed, from its first question. There is nothing to create per customer.

The security brief sets out the separation in full, and where it stops.

Each customer on its own database

If every customer has a database of its own with the same tables, make the platform key with Each organisation has its own database switched on, then give each customer a route under Widget › Organisations: the token names the customer, the route names its database. A customer with no route opens no session, and removing or moving a route ends that customer's sessions alone.

To add a customer, open a database whose schema you approved and choose New database like this: the new customer's database is approved as its twin when its tables match, and the glossary and the verified golden questions come with it.

Adding customers from your own software

Your sign-up flow can do the same as it creates a customer. An API key holding organisations.write, and nothing else, reaches /api/v1/organisations: add a customer from the template, route or move one, let one go, and list them.

That key can do nothing the dashboard refuses, and Sonela records every change with the key's name. The API guide has the requests.

Narrowing what one person reads

Inside one customer, an access profile (Data sources › Access profiles) hides tables and columns from one audience, and reads a table's rows only where a column equals a value your server signs. Name it in the same token: profile for the profile, profile_claims for its values. The values reach your database as separate parameters the AI never sees, and a key can be fixed to one profile instead.

Two assistants, different material

Each signed-in key reads every manual, API lookup and document template, or only the ones you tick, so a back-office assistant and the one in your customer portal can read different material from one workspace. A change applies from the next question of every open session, with no new tag and no new token.

The language each key speaks

A key answers in the one you choose of English, German, French, Spanish, Italian and Albanian, whatever the question's language; the language travels in the session, not in the page. Serve customers in two markets with two keys.

Customers come and go

  • A new customer: sign its id. Nothing changes in Sonela.
  • A customer who leaves: stop signing its id. No new session opens for them; a token already issued lasts until it expires, so keep it to minutes, and an open session for at most 30 minutes.
  • A new domain: add it to the key's sites. The key stays the same, so no page changes.
  • A key per customer still works too, if you prefer it: each one names its customer when you create it.

Building it into your product?

Tell us what your platform looks like — how customers are separated, where people sign in — and we will walk the first integration through with you.

Write to us sonela.ai