Data planeAssert logged in

POST /v1/sessions/{session_token}/logged-in

Assert that a session's visitor authenticated in your application. Private-key authenticated, body-less by design, idempotent.

curl -X POST \
  https://api.botect.ai/v1/sessions/sess_9f3c.../logged-in \
  -H "Authorization: Bearer sk_YOUR_PRIVATE_KEY"
{
  "logged_in": true,
  "asserted_at": "2026-09-01T10:15:00Z"
}

Call this from your login handler after a successful sign-in. Authenticated by the private key (secret), like the verdict endpoint, and against the same session token.

POST https://api.botect.ai/v1/sessions/{session_token}/logged-in

Botect records a timestamp and nothing else — see Logged-in visitors for what the assertion buys and how long it lasts.

Authentication

Private key via Authorization: Bearer sk_… (or the X-Botect-Private-Key header). The session must belong to the authenticated project. See Authentication.

Authorization: Bearer sk_YOUR_PRIVATE_KEY

Server-side only. Calling this from the browser would let any script — including the automation you are paying to detect — claim to be signed in.

Path parameters

path
session_tokenstring
Required

The session token your SDK obtained from ingest — the same one you pass to the verdict endpoint.

Request body

None. This endpoint rejects any request body and any query string with a 422.

That is the privacy guarantee made structural: there is no field in which a user id, email, or account reference could reach Botect, so none can arrive by mistake. An empty JSON container ({}) is tolerated, since many HTTP clients send one on a body-less POST.

Example

Response fields

logged_inboolean
Required

Always true on success — the assertion is recorded.

asserted_atstring
Required

ISO-8601 timestamp of the current assertion, which is what the protection window is measured from. Expiry is this value plus 24 hours, so you can compute it directly from the response.

Idempotency

Repeats are safe and expected — call this on every login, not just the first. Each call restarts the 24-hour window and returns the new asserted_at.

No idempotency key is needed: the operation is a timestamp write, so replaying it is indistinguishable from asserting again.

Errors

StatuscodeWhen
401UNAUTHENTICATEDMissing / bad private key, or scoring not enabled
402NO_ACTIVE_SUBSCRIPTIONOwning account has no active subscription
404UNKNOWN_SESSIONNo such session for this project
422INVALID_PAYLOADA request body, a query string, or a malformed session token

Unlike the verdict endpoint — a read that fails open — this is a write, so an assertion that did not land says so with a 404 rather than a cheerful 200. A token belonging to another project returns the same 404 as one that does not exist, so the endpoint never reveals which tokens are real.

A 404 most often means the login beat the collector: the session row is created by the SDK's first report, roughly half a second after page load. Retry once, or assert after the visitor's first navigation.