Security and audit
List sign-ins
Returns sign-in attempts of the workspace’s members, newest first, one page at a time. Each one says how the person signed in, whether it worked (and why not), where it came from and whether the device or country was new for that account.
- Bearer API key
- Scope:
adminonly - or app session
- Workspace:
X-Tenant-ID(optional with a key)
Headers
AuthorizationstringrequiredYour API key as
Bearer <key>. The wordBearerand the space are case-sensitive. Browser clients signed in to the app use the session cookie instead.X-Tenant-IDuuidoptionalWorkspace id. Optional with an API key (a key always acts in its own workspace); if you send it, it must match the key’s workspace. Required with a session cookie. You can pass
?tenant=<id>instead.
Query parameters
user_iduuidoptionalOnly this teammate (their user id,
user_idin the members list).resultenumoptionalsuccessorfailure. Leave it out for both.fromtimestampoptionalOnly entries from this time on. RFC 3339 (
2026-10-01T00:00:00Z) or a date (2026-10-01).totimestampoptionalOnly entries before this time (exclusive). RFC 3339 or a date: to include all of 8 October, send
to=2026-10-09.cursorstringoptionalThe
next_cursorof the previous page, unchanged. Leave it out to get the first page.limitintegeroptionalItems per page.
Response
200 OKapplication/json
itemsarray<LoginEvent>Sign-ins, newest first.
Show child attributesHide child attributes15
idstringSign-in id.
user_iduuidnullableThe account that signed in or was tried.
nullwhen no account matched.user_namestringName of that account, or
"".emailstringEmail address used to sign in.
methodenumpassword,google,invite(signed in by accepting an invite) orsignup(signed in by creating the account).resultenumsuccessorfailure.reasonenumWhy a sign-in failed:
bad_password,unknown_account(no account with this email),disabled(the account is disabled),google_conflict(the email is linked to a different Google account) orgoogle_unverified(Google has not verified the email).""for successful sign-ins.ipstringIP address the attempt came from.
locationstringCity and country of the IP address, for example
Ljubljana, SI, or only the country (SI).""when unknown.countrystringTwo-letter country code of the IP address, or
"".citystringCity of the IP address, or
"".devicestringBrowser and operating system, for example
Chrome on macOS, or"".new_devicebooleantruewhen the account had not signed in from this device before.new_countrybooleantruewhen the account had not signed in from this country before.created_attimestampWhen it happened (RFC 3339).
next_cursorstringSend it as
cursorto get the next page. An empty string ("") means this is the last page.
Status codes
- 200OK. One page of sign-ins.
- 400Bad request. A filter is malformed:
invalid fromorinvalid to(neither RFC 3339,YYYY-MM-DDnor unix seconds),invalid user_id,invalid resultorinvalid cursor. A session request without a workspace getsworkspace required (X-Tenant-ID). - 401Unauthorized. The API key is unknown, revoked or expired (
invalid or expired API key), or there is no key and no signed-in session (unauthorized). - 403Forbidden. The API key does not have the
adminscope (this endpoint needs an API key with the admin scope:readandwritekeys cannot read security data); the key is limited to other IP addresses (this API key is not allowed from your IP address,code: "ip_not_allowed"); or the key or user belongs to another workspace (API key belongs to a different workspace,forbidden). - 500Server error. Something went wrong on our side. Retry with backoff.
Whose sign-ins are returned?
- Owners, admins and
adminAPI keys get the sign-ins of every member of the workspace. Filter one person withuser_id. - Agents signed in to the app only get their own sign-ins:
user_idis always set to themselves.
How do I page through the list?
Items come newest first, limit at a time (50 by default, at most 200). While next_cursor is not empty, call the endpoint again with the same filters and cursor=<next_cursor>. An empty next_cursor ("") means you have the last page.