Security log
Trace what your agents' security did — each check on a request, what it decided and why, and each change to the security settings, by whom — each row in full, filtered, a page at a time, and downloadable. Admins only.
The Security log shows each request your agent's security checked — which check, what it decided and why — and each change to the agent's security settings, newest first. Use it to trace what happened: your key in an app you don't know, an old app version that can't prove itself, a person who couldn't be verified, a switch someone turned off.
Where: Security → Security log for all your agents at once (the Overview tab shows the five latest rows, with Open the Security log). For one agent, Embed & Widgets → Install → Your app and your users → What we've seen, under the counts — with Open in the Security log to see that agent's rows on the full page. Only Admins can open it.
What each row shows
| Column | What it says |
|---|---|
| Time | When it happened, in your own time zone. Hover for the exact time in UTC. |
| Agent | On the Security log page, the agent the request was for. A change that serves every agent says Every agent. |
| Check | Only my apps, Verified app, Verified user, Server token, Bot check, Key (a publishable key you revoked) or Allowed domains (a website the agent doesn't list). |
| Result | Allowed, Verified, Refused or Anonymous — or, while a switch is report-only, Would be refused (Would be anonymous for a person not yet proven in a chat or call). Hover for what it means. |
| Why | In plain English — An app ID that is not listed, No server token, An expired identity token, The request didn't say which app it is — with ×N when it repeated (hover for when it last did). |
| App | The app ID the app declared, or the website's address. Not sent when an app didn't say which app it is. |
| Platform | iPhone, Android, App or Website, with the SDK version when the request names it. |
| Install | A short one-way code for the app install or browser: the same install always shows the same code, and its ID is never shown. |
| Where | Which part of the agent: Start-up, Chat or call, Call, Devices, Memory, Booking, Past conversations, App proof… and the country the request came from. |
A change to the security settings is a row of its own: what changed, in a sentence — Turned on Only my apps, Added iPhone app com.acme.app (Team ABCDE12345), Revoked a publishable key, Changed allowed domains — and who made it, by name from your team and their role. Never a secret, a key or a token. A change that serves every agent, such as a Play Integrity key, shows in every agent's log.
One row in full
Click a row — or move to its time with Tab and press Enter — to open it in a panel beside the log (Esc closes it). For a check, the panel shows:
- What this means and What to do — for every reason a row can carry, in plain English: The app named an app ID that isn't under Your apps. If it is your app, add its bundle ID or package name…
- Details, each with its own label: when it happened, in your time and in UTC (for a row counted ×N,
when it was first and last seen, and how many times); the check, the result and why; the switch at
the time (Only my apps was on, Server tokens was report-only); the app, platform, SDK version,
app version, install, where and country. And, when the request had them:
- How the app proved itself — Apple App Attest, Google Play Integrity (with Google's verdict, such as recognised by Google Play, meets device integrity), a registered debug token (shown by the name it has in your settings today, or a debug token since removed), or an earlier proof on the same install — and whether it was a production or a development build.
- How the person was proven — your sign-in's ID token (JWT), a signed user ID (HMAC), a token from your server, or a test user — with the exact reason a token was turned down: from another issuer, for another audience, expired, not valid yet, a bad signature, an unknown signing key, no user ID claim, a different user, or not readable. For an ID token, the sign-in issuer (its host) and the signing key (its key ID and algorithm).
- Server token — the scopes the request needed, the scopes the token held, and the token's key ID.
- Bot check provider — Cloudflare Turnstile or reCAPTCHA Enterprise.
- Request ID and Answered with — the status the app or page received, such as 403 Refused or 200 OK. A row counted ×N also shows the latest request's ID and answer.
- How it was decided — every check the request met, in order, each marked ✓ (passed), ✗ (refused), Report only or Anonymous.
- Shortcuts — Show every row of this request, Everything from this install, Everything from this app and Everything from this check set the log's filters to that request, install, app or check; Open the agent's security settings; and Copy as JSON, the row exactly as it is kept (without the agent's or the person's name the page adds).
A change opens the same way: what changed, before → after for a switch or a value (Off → On, Report only → Enforce, 2 → 3), when, and who made it — their name from your team, their role and their member ID.
The app version shows only when the app sends one. Today the SDKs send it with a device's registration for calls (Devices), so rows from other parts of the agent don't have it.
Match a report to a row: the request ID
Every answer to a request the security checks see carries a response header, X-Graine-Request-Id — a
16-character code for that one request. It is the Request ID in the row's panel. When an app or a
page reports a problem, note the code with the time: in a browser it is in the network tab, and readable
by the page's own script; in an app, in your network logs. Paste the request ID from an error into the
log's search box to find its rows — it is looked for across the whole year. A row counted ×N keeps the
first request's ID and the latest one's.
How rows are grouped
- A refused request is one row: the check that refused it. Nothing that request passed, and nothing report-only, is logged beside it. The same install refused again within a minute is counted on that row (×N).
- A pass (Allowed, Verified) is one row per install and check every 10 minutes.
- A report-only or anonymous result (Would be refused, Would be anonymous, Anonymous) is one row per install, check and reason every 10 minutes, whichever part of the agent it came from — the first is kept, the rest are counted on it (×N).
- A request with no install — a website without one, or an app's start-up request before the app has proven itself — is grouped by the app ID or website instead, and shows no install code.
- Under a flood, at most 60 new rows a minute of one kind, and 2,000 a day per agent, are added; the rest are counted on the latest matching row, and the first row of each kind in a day is always kept.
Filter, page and share
Filter by time (24 hours, 7 days, 30 days, 90 days or a year), everything, checks or changes, result, check, app ID or website (any part of it) and, on the Security log page, agent — type part of its name. Everything from this install in a row's panel filters to one install; remove it with the × on its chip. The filters are applied by Graine before anything is sent to your browser, and they stay as you move between pages; a new filter starts again at page 1.
A page holds 25, 50 or 100 rows. It says where you are — 1–50 of 312 — counted up to 10,000 (10,000+ past that), with Previous and Next. New rows arriving while you read don't move the page you are on.
The Security log page keeps its filters in its address — agent, time, kind, result, check, app ID, install, request ID and page size — so you can bookmark a view or send it to another Admin.
Download
Download CSV saves the current filter: up to 10,000 rows, newest first, times in UTC. A change names the member ID and role of whoever made it. Each download is recorded in the activity log.
How long, and what is never logged
Rows are kept for a year. If the log ever reaches its size limit, passing rows older than 30 days are removed first, so refusals and report-only rows stay for the year.
Never logged: IP addresses, user IDs, names, phone numbers, emails, identity tokens, server tokens, app proofs, publishable keys or any secret. An install is only ever its one-way code.
A row's detail adds codes and public facts only, and at most about 1 KB of them: a registered debug token's ID, never the token or its name (the panel looks the name up in your settings when you open the row); an ID token's issuer host and key ID, never the token or the person it names; a server token's scopes and key ID, never the token; Google Play's verdict words, never a device ID.
Next
- Secure your agent — the switches the log reports on, and how to roll them out report-only first.
- Server tokens, Rotating the publishable key and the website bot check.
- Secure your workspace — the Security page's Overview.

