Okta’s System Log API lets you inspect authentication events programmatically, but its real power comes from understanding how it models time and identity.

Let’s say you want to see all successful sign-ins for a specific user within the last hour. Here’s how you’d craft that query using curl:

curl -v -X GET \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SSWS <YOUR_API_TOKEN>" \
  "https://<YOUR_OKTA_DOMAIN>/api/v1/logs?filter=eventType eq \"user.session.start\" and actor.alternateId eq \"user@example.com\" and published gt \"$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ)\""

This curl command hits the Okta /api/v1/logs endpoint. The key is the filter parameter.

  • eventType eq "user.session.start": This narrows down the log entries to only successful user sessions. Okta has a vast array of event types, and user.session.start is the specific code for a successful login.
  • actor.alternateId eq "user@example.com": This targets events where the actor (the entity performing the action) has an alternateId (typically the user’s primary email or username) matching user@example.com.
  • published gt "$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ)": This is where time comes in. published refers to the timestamp when the event was recorded. gt means "greater than." The date command dynamically generates an ISO 8601 formatted timestamp for one hour ago, ensuring we only get recent events.

The Authorization: SSWS <YOUR_API_TOKEN> header is crucial for authentication. Replace <YOUR_API_TOKEN> with a valid Okta API token that has at least "View system logs" permissions. The <YOUR_OKTA_DOMAIN> should be your actual Okta tenant URL, like mycompany.okta.com.

Okta’s System Log API is built around a robust event model. Each log entry is an object containing details about the event, including:

  • eventType: The type of action that occurred (e.g., user.session.start, user.session.end, user.account.update_profile).
  • actor: Information about the entity that initiated the event. This includes id, type, and alternateId.
  • displayMessage: A human-readable summary of the event.
  • outcome: Whether the event was successful or failed.
  • published: The ISO 8601 timestamp of when the event occurred.
  • request: Details about the request that triggered the event, including ipAddress and userAgent.
  • target: Information about the entity that was affected by the event.

You can query on virtually any field within these log objects. For instance, to find failed sign-in attempts from a specific IP address:

curl -v -X GET \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: SSWS <YOUR_API_TOKEN>" \
  "https://<YOUR_OKTA_DOMAIN>/api/v1/logs?filter=eventType eq \"user.session.login.fail\" and outcome.result eq \"FAILURE\" and request.ipAddress eq \"192.168.1.100\""

This query uses eventType eq "user.session.login.fail" and outcome.result eq "FAILURE" to pinpoint failed login attempts, and request.ipAddress eq "192.168.1.100" to filter by a specific IP.

Okta’s filtering syntax is OGNL-like, supporting operators like eq (equals), ne (not equals), lt (less than), le (less than or equal to), gt (greater than), ge (greater than or equal to), sw (starts with), ew (ends with), co (contains), and in (in list). You can also combine multiple conditions with and and or.

A common pitfall is misinterpreting the published timestamp. It’s the time the event was recorded by Okta, not necessarily the exact moment the user clicked "login." For most practical purposes, this distinction is minor, but for ultra-precise auditing, be aware of the slight lag. Also, remember that Okta’s API has rate limits. If you’re making a high volume of requests, you’ll need to implement retry logic with exponential backoff.

When you start querying for specific user attributes, like actor.id or target.displayName, you’re interacting with the identity layer of the log events, which is distinct from the event type itself.

The next step after mastering basic event filtering is understanding how to correlate events across different types, perhaps by tracing a user’s journey from a sign-in attempt to a subsequent application access or MFA challenge.

Want structured learning?

Take the full Okta course →