> For the complete documentation index, see [llms.txt](https://docs.veilio.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veilio.xyz/documentation/basics/client-app-access-rights-governance-and-audit-logs.md).

# Client app: access rights, governance & audit logs

How to integrate Veilio inside your own application so that: end-users of your product never need a Veilio account, your backend owns roles and access decisions

### Architecture (who talks to whom)

```
End-user (logged into YOUR app)
        │
        ▼
Your backend (session + roles)
        │  API key (server-side only)
        ▼
Veilio API  →  AccessLog (+ optional SIEM)
```

Rules:

* The Veilio **API key never leaves your backend** (no browser, no mobile bundle).
* Your app authenticates the end-user (session / JWT / SSO).
* Veilio authenticates **your integration** (the API key tied to your Veilio org).
* On detokenize, pass the end-user identity with `username` so logs are meaningful.

***

### What Veilio logs by default

Each successful `DETOKENIZE` creates an access log with:

| Field                        | Meaning                                             |
| ---------------------------- | --------------------------------------------------- |
| API key / org user           | The Veilio account that owns the key (your company) |
| Token id / type              | Which token was revealed (not the plaintext)        |
| `reason`                     | Optional business context you send                  |
| `username` → `actorUsername` | **End-user of your app** (optional but recommended) |
| IP / user-agent              | Usually your **backend** server, not the browser    |
| Timestamp / success          | When it happened                                    |

Without `username`, the log only says “your API key revealed token X”.\
With `username`, it says “**end-user PERSONX** triggered a reveal via your app”.

View logs in the Veilio dashboard (**History** / admin logs) or export them to your SIEM (see [SIEM integration](https://docs.veilio.xyz/documentation/webhooks/siem-integration)).

***

### Use case 1 : Attribute every reveal to the end-user

**Situation**\
Your product has its own users. They open a page that needs plaintext (send email, open a record, export). Your backend calls Veilio with your org API key. You need the Veilio journal to show **which of your users** caused the reveal, without creating Veilio logins for them.

**Pattern**

1. Resolve the authenticated session in **your** app (`session.username`, `session.userId`, …).
2. Call `detokenize` from the backend and pass `username` (stable human-readable id: login, email local-part, or opaque staff id).
3. Optionally set `reason` for context (`open_record`, `send_notification`, …).

#### JavaScript / TypeScript

```ts
import { VeilioClient } from "@veilio/sdk";

const veilio = new VeilioClient({
  apiKey: process.env.VEILIO_API_KEY!,
  baseUrl: process.env.VEILIO_BASE_URL || "https://app.veilio.fr/api",
});

/**
 * Called from YOUR authenticated route handler.
 * `session` comes from YOUR auth — never from Veilio.
 */
export async function revealField(session: {
  username: string;
}, token: string) {
  const { data, accessedAt } = await veilio.detokenize({
    token,
    username: session.username, // → AccessLog.actorUsername
    reason: "open_record",
  });

  return { data, accessedAt };
}
```

#### HTTP

```http
POST /api/detokenize
X-API-Key: vk_live_...
Content-Type: application/json

{
  "token": "tok_...",
  "username": "alice.dupont",
  "reason": "open_record"
}
```

#### Python

```python
result = client.detokenize(
    token="tok_...",
    username=session["username"],
    reason="open_record",
)
```

**Result in Veilio logs**

* Org / API key: your integration
* **Username:** `PERSON.01` (your end-user)
* Reason: `open_record`
* Token type / id: which field was revealed

***

### Use case 2 : Role-based reveal (your app decides)

**Situation**\
Several roles can open the same screen (`role1`, `role2`, `role3`), but only some roles may see plaintext. Veilio does **not** know your RBAC. Authorization stays in your app; Veilio records the reveal when you call the API.

**Pattern**

* Gate detokenize with your role check **before** calling the SDK.
* If the role is not allowed: return tokens / masked values only: **no** detokenize call.
* When allowed: detokenize and still pass `username` (use case 1).

#### Example

```ts
type AppRole = "role1" | "role2" | "role3";

/** Only role1 may reveal plaintext in this flow. */
const CAN_DETOKENIZE: ReadonlySet<AppRole> = new Set(["role1"]);

export async function loadSensitiveField(
  session: { username: string; role: AppRole },
  token: string
): Promise<{ value: string; revealed: boolean }> {
  if (!CAN_DETOKENIZE.has(session.role)) {
    // role2 / role3: see the token or a masked placeholder — no Veilio reveal
    return { value: token, revealed: false };
  }

  const { data } = await veilio.detokenize({
    token,
    username: session.username,
    reason: `reveal_by_${session.role}`,
  });

  return { value: data, revealed: true };
}
```

Same idea with an explicit variable before the SDK call:

```ts
const allowDetokenize = session.role === "role1";

if (allowDetokenize) {
  const { data } = await veilio.detokenize({
    token,
    username: session.username,
    reason: "authorized_reveal",
  });
  // use plaintext `data`
} else {
  // keep `token` / masked UI — do not call Veilio
}
```

***

### Governance checklist

| Topic                               | Owner                                | Notes                                   |
| ----------------------------------- | ------------------------------------ | --------------------------------------- |
| Login / session                     | Your app                             | End-users never sign in to Veilio       |
| Roles (`role1` / `role2` / `role3`) | Your app                             | Enforce **before** detokenize           |
| API key storage                     | Your backend / secrets manager       | One key per environment                 |
| Who was revealed for                | Veilio audit (`username` + `reason`) | Pass on every reveal                    |
| SIEM / SOC                          | Veilio webhook → your stack          | Same events, including `actor.username` |

Recommended:

* Always send `username` on detokenize (and bulk / format when applicable).
* Always send a short, stable `reason`.
* Never detokenize “just in case” on page load for every role.
* Never log plaintext returned by Veilio into your application logs.

***
