Endpoint summary
GET /v1/sessions
Returns one row per session with the latest decision summary. Requires a secret key with the sessions:list scope. The default scopes for a secret key don’t include sessions:list, so add it to keys that list sessions.
Supported query parameters:
Rows are ordered by the time of each session’s latest decision, newest first. A
limit, verdict, client_user_id, or cursor value that isn’t valid returns 422 with request.validation_failed, and the offset parameter isn’t supported. See Pagination for how to page through results.
search matches in one of two ways:
- A value that starts with
sid_,evt_, orvid_matches a session ID, event ID, or visitor ID exactly, ignoring case. A 32-character hexadecimal value matches a legacy session ID or event ID exactly. - Any other value is a case-insensitive substring match against the session ID, event ID, visitor ID,
client_user_id, page URL, user agent, and IP address.
latest_decision carries these fields:
Look up a user’s sessions
After you attach your own user ID to sessions withPATCH /v1/sessions/:sessionId, pass the same value as client_user_id to list every session for that user:
422. You can combine client_user_id with verdict and search, and page through the results with cursor as usual; send the same client_user_id with each cursor. To read the signals for a session in the list, retrieve it with GET /v1/sessions/:sessionId.
Use client_user_id rather than search to find a user’s sessions. search matches substrings across several fields, so it can also return sessions for other users whose IDs contain the value.
GET /v1/sessions/breakdown
Counts the sessions that match a set of filters, grouped by one dimension, with the number of bot, human, and inconclusive verdicts in each group. Use it to answer questions such as which browsers account for the sessions from one city, or which networks the bots on a platform come from. Requires a secret key with the sessions:list scope.
Supported query parameters:
Each group’s
value is in the form its filter parameter accepts, so you can pass it back to this endpoint as a filter to narrow further. For city groups, pass the group’s country_code as country along with the city. GET /v1/sessions filters only by verdict and client_user_id (and search), so it can list the sessions in a verdict group or for one user, but not in a browser, platform, location, or network group. A test key counts test sessions and a live key counts live sessions.
An unknown parameter, a value that isn’t valid, or a parameter that is empty or given more than once returns 422 with request.validation_failed. Foil rejects these rather than ignoring them so that a misspelled or malformed filter can’t return counts for sessions you didn’t ask about. A breakdown that doesn’t finish within 20 seconds returns 503; narrow since and until or add filters, then retry. Counts include new decisions within about five minutes.
For example, to see the top browsers among sessions from Austin in September:
Sessions whose platform or browser Foil doesn’t recognize are grouped under
other when you group by platform or browser. An iPad that requests desktop websites is counted as macos.
GET /v1/sessions/:sessionId
Requires a secret key with the sessions:read scope. A session that doesn’t exist, or that belongs to the other environment, returns 404 with request.not_found.
Returns the full public investigation view for one session. The response is intentionally ordered so the most actionable fraud analysis appears first, followed by continuity context, then structured evidence and lower-level telemetry.
Unlike GET /v1/sessions, which stays a compact summary surface with latest_decision, session detail uses the richer decision, highlights, signals_fired, and client_telemetry model shown below.
Example response:
decisionis the current session outcome in public, action-oriented terms.automation_statusmaps toautomated,human, oruncertain, whiledecision_statustells you whether the current result ispreliminaryorfinal.highlightsis a curated explanation layer capped at five items, including both concerning and reassuring findings.attribution,web_bot_auth,network, andruntime_integritysummarize the strongest fraud and classification context.attribution.labelsidentifies what is behind the session. Each label has akind(actor,provider,tool,product,organization,purpose,environment,trust, orevasion), a flat stringvaluesuch asautomation,ai-agent, orplaywright, a displaylabel, and aconfidencefrom0to100.attribution.behaviorsdescribes how input reached the page, by channel.attributionisnullwhen Foil has nothing to attribute.- Each
runtime_integrityfield is one ofclean,notice,elevated, orhigh_risk. visitor_fingerprintandconnection_fingerprintprovide continuity and transport identity context.visitor_fingerprint.resolutiontells you how the session was linked to the visitor ID.native_runtime_integrity,native_app,native_carrier,native_motion_print,device_identity, andinstall_idarenullfor browser sessions. Sessions from the iOS and Android SDKs can populate them, but each field is stillnullwhen Foil doesn’t have its data for the session, so check each one before you read it.behaviorisnullunless behavior data is enabled for your organization and available for the session.signals_firedis the structured machine-usable signal summary;highlightsis the editorial explanation layer.client_telemetryis curated lower-level client telemetry for investigations. It is not a verbatim raw probe dump.
signals_fired.signal and highlights.evidence.signal are friendly string slugs. They are response values, not an exhaustive documented enum registry.
PATCH /v1/sessions/:sessionId
Sets or clears client_user_id, the ID of the end user in your own database. This is customer-supplied linkage only: it does not affect scoring, visitor fingerprints, sealed tokens, or browser/native SDK behavior.
Requires a secret key with the sessions:update scope.
null to clear it:
client_user_id. Foil applies these rules to its value:
Errors are
request.validation_failed responses with details.parameter_set set to session_update. A session that doesn’t exist, or that belongs to the other environment, returns 404.
The response is the same session detail resource returned by GET /v1/sessions/:sessionId, with the updated client_user_id. The list endpoint returns client_user_id on each row, and its client_user_id parameter lists every session for one user.