Live in your app in an afternoon
One script tag, one token your backend signs, and the roles you already have. We never get access to your code, your database or your API keys.
From script tag to first answer
Works with React, Vue, Angular and server-rendered apps.
// KirkyWidget.tsx · render it once, e.g. in App import { useEffect } from "react"; export function KirkyWidget() { useEffect(() => { const s = document.createElement("script"); s.src = "https://cdn.kirkyapp.com/v1/…"; s.setAttribute("data-kirky-tenant", "tn_4f7k2q"); s.async = true; document.body.appendChild(s); return () => s.remove(); }, []); return null; }
What you need
- 01
A web app you control
Any front end that renders HTML: React, Vue, Angular, Next.js or server-rendered pages. The widget mounts in a Shadow DOM, so your styles stay untouched.
- 02
A backend that can sign a token
An ES256 key pair. The private key stays on your server; you upload only the public key in the portal.
- 03
A workspace in the portal
Where you get your tenant ID, upload documents, register endpoints and decide what each role can see.
- 04
A modern browser for your users
Current Chrome, Edge, Firefox and Safari 16.4 or later. Strict CSP with a nonce, strict-dynamic and Trusted Types are supported.
Integrate in Test, switch on Live
Every organization gets a free Test environment. It has its own tenant ID, its own query limit and a less expensive model, so you can integrate without touching Live.
| Claim | Test | Live |
|---|---|---|
| Tenant ID | tn_test_4f7k2q | tn_4f7k2q |
| Cost | Free, with its own query limit | Your plan |
| Model | Less expensive, for integration | Full quality |
| Data | Separate from Live | Separate from Test |
| Widget | Shows a “Test” label | No label |
The token your backend signs
Your backend tells Kirky who the user is with a JWT signed with ES256. It lives five minutes at most, and a new role starts with no permissions until you grant them in the portal.
| Claim | Meaning | Required |
|---|---|---|
| sub | Your user’s ID. Kirky never needs their email or name.Required: Yes | Yes |
| roles | The user’s roles in your app. They decide what Kirky can read and do.Required: Yes | Yes |
| aud | Your tenant ID (Test or Live).Required: Yes | Yes |
| exp | Expiry, at most 5 minutes after issue. The SDK asks for a new one when it needs it.Required: Yes | Yes |
| lang | es or en. Answers follow it; without it, Kirky follows the browser.Required: No | No |
| kid (header) | Which of your public keys signed it, so you can rotate keys without downtime.Required: Yes | Yes |
Register the endpoints Kirky may read
For the Queries layer, Kirky calls your own read endpoints from the user’s browser, with that user’s session. Your credentials never reach our servers.
- 1Import your OpenAPI fileOr add endpoints by hand. The portal previews every endpoint Kirky will be able to call before anything is saved.
- 2Describe each endpoint in plain wordsKirky picks the endpoint from its description, so “open orders for the signed-in seller” beats “GET /orders”.
- 3Choose which roles can use itAn endpoint no role can use is never called. Write endpoints go to the Actions layer and always ask for confirmation.
- 4Pass the user’s auth headersCookies work as they are. For bearer tokens, give the SDK a getAuthHeaders() function; it runs in the browser, never on our side.
// app.ts · bearer-token apps only Kirky.init({ token, getAuthHeaders: () => ({ Authorization: `Bearer ${session.accessToken}`, }), });
Notes by framework
React and Next.js
Render the widget component once near the root, and initialize after your own login resolves. In Next.js, load it from a client component.
Vue
Load the script in onMounted of your root component and initialize once the user is known. It works the same with Nuxt on the client.
Angular
Add the tag to src/index.html, then initialize from a component or service after authentication. No module to import.
Server-rendered apps
Add the tag to your layout and point data-kirky-token-url at a same-origin route that returns the token. No inline script, so a strict CSP stays intact.
If something doesn’t work
The widget doesn’t appear
Check your Content Security Policy first: allow cdn.kirkyapp.com in script-src, or pass your nonce to init(). Then open the browser console with debug: true and read what diagnostics() reports.
The token is rejected
The usual causes are an aud that doesn’t match the environment (Test vs Live), an exp longer than 5 minutes, a kid the portal doesn’t know, or a server clock that is off by more than a minute.
Data questions fail but documents work
Your endpoint probably rejects the browser’s preflight. Allow the tracing headers your APM tool adds (traceparent, baggage, sentry-trace), and check that getAuthHeaders() returns a fresh token.
A role sees too little, or too much
Roles come from the token. Open the role in the portal: a new role starts with no permissions, and each layer and endpoint is granted separately.