API Reference
Complete REST API documentation for the Stradum behavioral biometrics platform.
Introduction
Stradum uses behavioral biometrics to verify identity. The API accepts behavioral events from the JavaScript SDK, manages sessions and identities, runs analysis, and delivers results via webhooks and a real-time dashboard.
The typical integration flow is:
- SDK captures behavioral events during form interaction
- Customer server completes the session and links it to an identity
- Analysis is triggered, producing match scores and reason codes
- Results are delivered via API response, webhooks, and dashboard
Base URL
https://api.stradum.com/api/v1
All endpoints are prefixed with /api/v1.
Error Handling
The API uses standard HTTP status codes. Error responses include a JSON body:
{
"detail": "Session not found"
}
| Status | Meaning |
|---|---|
| 200 | Success |
| 201 | Resource created |
| 204 | Deleted (no content) |
| 401 | Missing or invalid API key / JWT token |
| 403 | Key lacks permission for this endpoint (e.g. publishable key on server-only route) |
| 404 | Resource not found |
| 402 | Payment required — trial limit reached or trial expired |
| 422 | Validation error — check request body |
| 429 | Session quota exceeded (org limit) |
| 500 | Internal server error |
Rate Limits
Default limits to ensure system stability:
- Event batches: max 5,000 events per request
- Sessions: max 100,000 events per session
- Session ID: 1–128 characters
What is a Session?
A session is one meaningful form interaction — from page load through submission or abandonment. Each time a person interacts with a form instrumented with Stradum, that creates a session.
Billable sessions: Only sessions with real behavioral activity (100+ events) count toward your org's quota. Accidental page loads, bots that leave immediately, and sessions with minimal interaction do not consume your trial or plan limit. This threshold ensures you're charged for genuine form-filling activity, not noise.
Trial limits: Self-serve signups get a 30-day trial with up to 1,500 billable sessions. When either limit is reached, the API returns 402 Payment Required on event ingestion until you subscribe.
JavaScript SDK
Installation
Add the SDK script tag to your page. No build step or npm install required.
<script src="https://api.stradum.com/sdk/v1/stradum.min.js"></script>
The SDK exposes a global Stradum namespace. Size: < 25KB gzipped. Current version: 0.1.0
Methods
Stradum.init(config)
→ string (sessionId)
Initialize the SDK and begin capturing behavioral events. Returns the session ID.
| Config | Type | Default | Description |
|---|---|---|---|
| apiUrl | string | required | Base URL for the Stradum API |
| apiKey | string | required | Publishable API key (pk_live_ or pk_test_). Sent as X-Stradum-Key header on all requests. |
| sessionId | string? | auto | Pre-generated session ID |
| captureValues | boolean | false | Capture field values (test environments only) |
| autoStart | boolean | true | Begin capturing immediately |
Stradum.getSessionId()
→ string | null
Returns the current session ID for post-submission linking. Returns null if not initialized.
Stradum.setMetadata(metadata)
→ object | null
Merge metadata into the session. Call at any time when candidate_id, report_id, or other keys become available. Sends a POST to the metadata endpoint. Returns the metadata object on success, null if not initialized.
// Associate metadata anytime during the session
Stradum.setMetadata({
candidate_id: 'c_abc123',
report_id: 'r_456'
});
Stradum.complete(options?)
→ { sessionId, summary, eventCount }
Signal form submission. Captures a form_submit event, generates a summary, and flushes all buffered events. Call this in your form's submit handler.
| Option | Type | Description |
|---|---|---|
| fieldValues | object | Collected field values for linking |
Stradum.getStats()
→ { sessionId, eventCount, summary, isActive }
Get current session statistics without stopping capture.
Stradum.stop()
Stop capturing and flush all buffered events via sendBeacon.
Stradum.reset()
Reset the SDK state for a new session. Stops capture and clears all internal state.
Stradum.isActive()
→ boolean
Check if the SDK is initialized and actively capturing events.
Typical Integration Flow
Complete end-to-end example showing SDK initialization, metadata association, form submission, identity linking, and analysis triggering.
<!-- 1. Include the SDK -->
<script src="https://api.stradum.com/sdk/v1/stradum.min.js"></script>
<script>
// 2. Initialize with your publishable key — capture begins automatically
const sessionId = Stradum.init({
apiUrl: 'https://api.stradum.com',
apiKey: 'pk_live_your_publishable_key'
});
// 3. Associate metadata when it becomes available
Stradum.setMetadata({
candidate_id: 'c_abc123',
report_id: 'r_456'
});
// 4. On form submit — complete the session client-side
document.querySelector('form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = Object.fromEntries(new FormData(e.target));
// Signal completion to SDK (flushes events)
Stradum.complete({ fieldValues: formData });
// 5. Send to your server with the session ID
await fetch('/your-server/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...formData, stm_session_id: sessionId })
});
});
</script>
Server-Side (Your Backend)
# Your server receives the form submission with stm_session_id
# All server-side calls use the secret key
headers = {"X-Stradum-Key": "sk_live_your_secret_key"}
# 6. Resolve identity (creates if new)
identity = requests.post("https://api.stradum.com/api/v1/identities/resolve",
params={"external_id": user.email},
headers=headers
).json()
# 7. Complete the session
requests.post(f"https://api.stradum.com/api/v1/sessions/{stm_session_id}/complete",
json={
"identity_id": identity["identity_id"],
"field_values": {"first_name": "John", "email": "john@example.com"}
},
headers=headers
)
# 8. Link session to identity (with account context)
requests.post("https://api.stradum.com/api/v1/identities/link",
json={
"session_id": stm_session_id,
"identity_id": identity["identity_id"],
"account_id": "acct_1",
"account_name": "Acme Corp"
},
headers=headers
)
# 9. Trigger analysis
analysis = requests.post("https://api.stradum.com/api/v1/analysis/trigger",
json={"session_id": stm_session_id},
headers=headers
).json()
# 10. Use the result
if analysis["match_status"] in ("review", "mismatch"):
flag_for_review(stm_session_id)
MCP Server
AI Assistant Integration
Stradum provides a Model Context Protocol (MCP) server that lets AI assistants (Cursor, Claude Desktop, and other MCP-compatible tools) query your behavioral biometrics data directly.
Available Tools
| Tool | Description |
|---|---|
| list_sessions | List recent sessions with optional filters |
| get_session | Get details for a specific session |
| get_session_detail | Get enriched session data with timeline and metadata |
| get_analysis | Retrieve analysis results for a session |
| trigger_analysis | Trigger analysis for a completed session |
| get_timeline | Get field-level interaction timeline |
| list_alerts | List recent signal alerts |
| get_overview | Get dashboard overview metrics |
| list_identities | List identity records |
| get_identity | Get a specific identity and its sessions |
| create_webhook | Register a new webhook endpoint |
Setup for Cursor
Add the following to .cursor/mcp.json in your project root:
{
"mcpServers": {
"stradum": {
"command": "npx",
"args": ["@anthropic/stradum-mcp"],
"env": {
"STRADUM_API_URL": "https://api.stradum.com",
"STRADUM_SECRET_KEY": "sk_live_your_secret_key"
}
}
}
}
Example Prompts
"Show me the latest 10 sessions and their match statuses"
"Analyze session stm_abc123 and explain the results"
"What are today's signal alerts?"
"Get the interaction timeline for session stm_abc123"
"Create a webhook for analysis.completed events at https://my-server.com/hooks"
Authentication
Overview
All API requests are authenticated via the X-Stradum-Key header. Dashboard routes use JWT bearer tokens.
API Key Types
Publishable Key (pk_live_*): Safe for client-side code. Used by the browser SDK. Can create sessions, send events, complete sessions, and update metadata.
Secret Key (sk_live_*): Server-side only. Never expose in client code. Can do everything publishable keys can, plus: retrieve analysis results, view session timelines, manage identities, manage webhooks.
Set via the X-Stradum-Key header.
# Client-side (SDK)
Stradum.init({
apiUrl: 'https://api.stradum.com',
apiKey: 'pk_live_your_publishable_key'
});
# Server-side
curl -H "X-Stradum-Key: sk_live_your_secret_key" \
https://api.stradum.com/api/v1/analysis/trigger
Dashboard Authentication (JWT)
Dashboard and user management routes use JWT bearer tokens obtained via POST /api/v1/auth/login. Include the token in the Authorization header.
curl -H "Authorization: Bearer eyJhbGciOi..." \
https://api.stradum.com/api/v1/dashboard/overview
Key management: Register an organization via POST /api/v1/auth/register to receive your initial publishable and secret key pair. You can generate additional key pairs and manage users from the Auth API.
/auth/register
Create a new organization and owner user. Returns the initial API key pair. No authentication required.
Request Body
| Field | Type | Description |
|---|---|---|
| org_name | string | Required. Organization display name. |
| string | Required. Owner's email address. | |
| password | string | Required. Owner's password. |
curl -X POST https://api.stradum.com/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"org_name": "Acme Corp",
"email": "admin@acme.com",
"password": "secure_password_here"
}'
Response 201
{
"org_id": "org_a1b2c3d4",
"user_id": "usr_x1y2z3",
"email": "admin@acme.com",
"publishable_key": "pk_live_abc123...",
"secret_key": "sk_live_xyz789..."
}
Important: The secret_key is only shown once at creation time. Store it securely.
/auth/login
Authenticate with email and password to receive a JWT token for dashboard access.
Request Body
| Field | Type | Description |
|---|---|---|
| string | Required. User email address. | |
| password | string | Required. User password. |
curl -X POST https://api.stradum.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{ "email": "admin@acme.com", "password": "secure_password_here" }'
Response 200
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user_id": "usr_x1y2z3",
"org_id": "org_a1b2c3d4",
"email": "admin@acme.com",
"role": "owner"
}
/auth/me
Get the currently authenticated user. Requires JWT authentication.
curl https://api.stradum.com/api/v1/auth/me \
-H "Authorization: Bearer eyJhbGciOi..."
/auth/keys
Generate a new API key pair for the organization. Requires JWT authentication with owner or admin role.
Request Body
| Field | Type | Description |
|---|---|---|
| label | string | Required. Human-readable label for the key pair (e.g. "Production", "Staging"). |
curl -X POST https://api.stradum.com/api/v1/auth/keys \
-H "Authorization: Bearer eyJhbGciOi..." \
-H "Content-Type: application/json" \
-d '{ "label": "Production" }'
Important: The secret_key is only returned once in this response. Store it securely — it cannot be retrieved again.
/auth/keys
List all API keys for the organization. Requires JWT authentication. Returns key metadata (prefix, label, created date) — secret keys are never returned.
curl https://api.stradum.com/api/v1/auth/keys \
-H "Authorization: Bearer eyJhbGciOi..."
/auth/keys/{"{key_id}"}
Revoke an API key pair. Both the publishable and secret keys will immediately stop working. Requires JWT authentication with owner or admin role.
curl -X DELETE https://api.stradum.com/api/v1/auth/keys/key_abc123 \
-H "Authorization: Bearer eyJhbGciOi..."
/auth/users
Invite a new user to the organization. Requires JWT authentication with owner or admin role.
Request Body
| Field | Type | Description |
|---|---|---|
| string | Required. New user's email address. | |
| password | string | Required. Initial password. |
| role | string | Required. One of: owner, admin, viewer. |
curl -X POST https://api.stradum.com/api/v1/auth/users \
-H "Authorization: Bearer eyJhbGciOi..." \
-H "Content-Type: application/json" \
-d '{
"email": "analyst@acme.com",
"password": "initial_password",
"role": "viewer"
}'
/auth/users
List all users in the organization. Requires JWT authentication.
curl https://api.stradum.com/api/v1/auth/users \
-H "Authorization: Bearer eyJhbGciOi..."
/auth/users/{"{user_id}"}
Update a user's role. Requires JWT authentication with owner or admin role.
Request Body
| Field | Type | Description |
|---|---|---|
| role | string | Required. New role: owner, admin, or viewer. |
curl -X PATCH https://api.stradum.com/api/v1/auth/users/usr_abc123 \
-H "Authorization: Bearer eyJhbGciOi..." \
-H "Content-Type: application/json" \
-d '{ "role": "admin" }'
/auth/users/{"{user_id}"}
Remove a user from the organization. Requires JWT authentication with owner or admin role. Returns 204 No Content on success.
curl -X DELETE https://api.stradum.com/api/v1/auth/users/usr_abc123 \
-H "Authorization: Bearer eyJhbGciOi..."
Sessions
/sessions
Initialize a new behavioral capture session. The SDK calls this automatically on init(), but you can also create sessions server-side. Requires X-Stradum-Key header with a publishable key (pk_live_) or secret key (sk_live_).
Request Body
| Field | Type | Description |
|---|---|---|
| session_id | string? | Pre-generated ID. Auto-generated if omitted. |
| metadata | object | Custom key-value pairs (candidate_id, report_id, etc.) |
| device_info | object | Device fingerprint data from the SDK |
curl -X POST https://api.stradum.com/api/v1/sessions \
-H "Content-Type: application/json" \
-H "X-Stradum-Key: pk_live_your_publishable_key" \
-d '{
"metadata": { "candidate_id": "c_abc123" },
"device_info": { "platform": "MacIntel" }
}'
Response 201
{
"session_id": "stm_a1b2c3d4",
"identity_id": null,
"status": "active",
"event_count": 0,
"created_at": "2026-03-07T12:00:00Z",
"metadata": { "candidate_id": "c_abc123" }
}
/sessions/events
Ingest a batch of behavioral events. The SDK sends these automatically — you typically don't call this directly. Requires X-Stradum-Key header with a publishable key.
Request Body
| Field | Type | Description |
|---|---|---|
| session_id | string | Required. The session to append events to. |
| events | EventPayload[] | 1–5,000 events per batch |
| sdk_version | string? | SDK version string |
| page_url | string? | Page URL where events were captured |
EventPayload
| Field | Type | Description |
|---|---|---|
| event_type | string | Event type (managed by SDK) |
| timestamp | float | Unix timestamp in seconds with ms precision |
| field_name | string? | Name of the form field (if applicable) |
| field_type | string? | text_input, protected_input, dropdown, checkbox, radio, textarea, date_selector |
| data | object | Event-specific payload data |
The SDK captures behavioral signals automatically. No configuration of event types is required.
Response 200
{
"session_id": "stm_a1b2c3d4",
"accepted": 45,
"rejected": 0,
"total_event_count": 245
}
/sessions/{"{session_id}"}/complete
Mark a session as completed. Typically called when the user submits the form. Optionally link to an identity and include field values. Requires X-Stradum-Key header with a publishable key (pk_live_) or secret key (sk_live_).
Request Body
| Field | Type | Description |
|---|---|---|
| identity_id | string? | Link to identity at completion time |
| field_values | object | Field name → submitted value map |
| metadata | object | Additional metadata to merge |
curl -X POST https://api.stradum.com/api/v1/sessions/ses_a1b2c3d4/complete \
-H "Content-Type: application/json" \
-H "X-Stradum-Key: pk_live_your_publishable_key" \
-d '{
"identity_id": "id_xyz789",
"field_values": {
"first_name": "John",
"last_name": "Smith",
"email": "john@example.com"
}
}'
Triggers a session.completed webhook if configured.
/sessions/{"{session_id}"}/metadata
Merge metadata into an active session at any time. Uses merge semantics — new keys are added, existing keys are overwritten. Call this whenever candidate_id, report_id, or other custom keys become available. Requires X-Stradum-Key header with a publishable key (pk_live_) or secret key (sk_live_).
curl -X POST https://api.stradum.com/api/v1/sessions/ses_a1b2c3d4/metadata \
-H "Content-Type: application/json" \
-H "X-Stradum-Key: pk_live_your_publishable_key" \
-d '{ "metadata": { "candidate_id": "c_abc123", "report_id": "r_456" } }'
Also available via the SDK: Stradum.setMetadata({ candidate_id: 'c_abc123' })
/sessions
List sessions with optional filters. Supports filtering by identity, account, status, match status, metadata, and analysis category. Requires Authorization: Bearer <jwt> header.
Query Parameters
| Param | Type | Description |
|---|---|---|
| identity_id | string | Filter by identity |
| account_id | string | Filter by account |
| status | string | active, completed, analyzed, abandoned, expired, rejected |
| match_status | string | match, review, mismatch |
| metadata_key | string | Filter sessions that have this metadata key |
| metadata_value | string | Exact match on metadata value (combine with metadata_key for key=value match) |
| category | string | Filter by analysis category |
| category_severity | string | Filter by category severity |
| page | int | Page number (default: 1) |
| page_size | int | Results per page (1–200, default: 50) |
# Find sessions for a specific candidate
curl "https://api.stradum.com/api/v1/sessions?metadata_key=candidate_id&metadata_value=c_abc123" \
-H "Authorization: Bearer eyJhbGciOi..."
/sessions/{"{session_id}"}
Retrieve a single session by ID. Returns the full SessionResponse. Requires Authorization: Bearer <jwt> header.
/sessions/{"{session_id}"}
Delete a session and all associated events. Returns 204 No Content on success. Requires Authorization: Bearer <jwt> header.
Identities
/identities
Create a new identity record. Identities represent individuals whose behavioral patterns are tracked across sessions. Requires X-Stradum-Key header with a secret key (sk_live_).
Request Body
| Field | Type | Description |
|---|---|---|
| external_id | string? | Your internal user/person ID |
| account_id | string? | Customer/employer account ID |
| account_name | string? | Human-readable account name |
| account_uri | string? | Account URL or URI |
| metadata | object | Custom metadata |
/identities/link
Link a session to an identity post-submission. This is the primary integration endpoint called by your server after form submission to associate the anonymous SDK session with a known person. Requires X-Stradum-Key header with a secret key (sk_live_).
Request Body
| Field | Type | Description |
|---|---|---|
| session_id | string | Required. The session to link. |
| identity_id | string | Required. The identity to link to. |
| account_id | string? | Tag session with this account |
| account_name | string? | Human-readable account name |
| account_uri | string? | Account URL |
curl -X POST https://api.stradum.com/api/v1/identities/link \
-H "Content-Type: application/json" \
-H "X-Stradum-Key: sk_live_your_secret_key" \
-d '{
"session_id": "stm_a1b2c3d4",
"identity_id": "id_xyz789",
"account_id": "acct_1",
"account_name": "Acme Corp"
}'
/identities/resolve?external_id={"{id}"}
Find or create an identity by your external ID. Idempotent — returns the existing identity if found, creates a new one if not. Use this when you know your internal user ID and want to ensure a Stradum identity exists for linking. Requires X-Stradum-Key header with a secret key (sk_live_).
curl -X POST "https://api.stradum.com/api/v1/identities/resolve?external_id=person_123" \
-H "X-Stradum-Key: sk_live_your_secret_key"
/identities
List identities. Optionally filter by account_id. Supports pagination via page and page_size. Requires Authorization: Bearer <jwt> header.
/identities/{"{identity_id}"}
Retrieve a single identity by ID. Returns the full IdentityResponse. Requires Authorization: Bearer <jwt> header.
Accounts
/accounts
List all customer accounts. Each account includes session and identity counts. Requires Authorization: Bearer <jwt> header.
Response 200
{
"accounts": [
{
"account_id": "acct_1",
"account_name": "Acme Corp",
"session_count": 342,
"identity_count": 87
}
],
"total": 1
}
Analysis
/analysis/trigger
Trigger behavioral analysis for a completed session. The session must be completed and linked to an identity. Analysis runs synchronously and returns the score, match status, confidence, and reason codes. Requires X-Stradum-Key header with a secret key (sk_live_).
Prerequisites: Session must be in completed status and linked to an identity via /identities/link or the identity_id param on /sessions/{'{id}'}/complete.
Request Body
| Field | Type | Description |
|---|---|---|
| session_id | string | Required. The completed session to analyze. |
| identity_id | string? | Override the session's linked identity |
curl -X POST https://api.stradum.com/api/v1/analysis/trigger \
-H "Content-Type: application/json" \
-H "X-Stradum-Key: sk_live_your_secret_key" \
-d '{ "session_id": "stm_a1b2c3d4" }'
Returns a ScoreResponse. Triggers analysis.completed and optionally signal.alert webhooks.
/analysis/session/{"{session_id}"}
Retrieve the stored analysis result for a session. Returns 404 if analysis hasn't been triggered yet. Requires X-Stradum-Key header with a secret key or Authorization: Bearer <jwt> header.
/analysis/identity/{"{identity_id}"}
Retrieve all analysis results for an identity. Returns an array of ScoreResponse objects. Requires X-Stradum-Key header with a secret key or Authorization: Bearer <jwt> header.
/analysis/session/{"{session_id}"}/score
Retrieve the public score for a previously analyzed session. Returns the score, match status, confidence, contributing signals, and human-readable reasons. Requires X-Stradum-Key header with a secret key (sk_live_) or Authorization: Bearer <jwt> header.
Response 200
{
"session_id": "stm_a1b2c3d4",
"identity_id": "id_xyz789",
"analyzed_at": "2026-03-07T14:30:00Z",
"result": {
"score": 84.2,
"match_status": "match",
"confidence": 0.92
},
"signals": ["typing", "mouse", "navigation"],
"reasons": [
{
"code": "typing_rhythm_match",
"category": "typing",
"severity": "none",
"description": "Typing rhythm consistent with baseline"
}
],
"context": {
"baseline_sessions": 5,
"summary": "Behavioral patterns are consistent with the identity's established profile."
}
}
See ScoreResponse schema for full field reference.
/sessions/{"{session_id}"}/timeline
Returns an abstracted field-level interaction timeline for a session. Provides a high-level view of how the user interacted with form fields, without exposing raw event data. Requires X-Stradum-Key header with a secret key (sk_live_) or Authorization: Bearer <jwt> header.
Response 200
{
"session_id": "stm_a1b2c3d4",
"duration_ms": 45230,
"field_count": 4,
"timeline": [
{
"field_name": "first_name",
"field_type": "text_input",
"focus_time_ms": 3200,
"keystroke_count": 12,
"paste_detected": false,
"revisits": 0
},
{
"field_name": "email",
"field_type": "text_input",
"focus_time_ms": 5100,
"keystroke_count": 22,
"paste_detected": false,
"revisits": 1
}
]
}
Dashboard
/dashboard/auth-check
Check whether dashboard authentication is required. No auth needed for this endpoint itself. Used by the frontend to determine whether to show the login gate.
Response 200
{ "auth_required": true }
/dashboard/overview
Dashboard landing page metrics. Returns total counts, today's activity, risk distribution, and recent sessions. Requires Authorization: Bearer <jwt> header.
Response 200
{
"total_sessions": 1247,
"total_identities": 342,
"total_accounts": 5,
"sessions_today": 47,
"alerts_today": 3,
"risk_distribution": { "match": 892, "review": 308, "mismatch": 47 },
"recent_sessions": [ /* SessionResponse[] */ ]
}
/dashboard/identity/{"{identity_id}"}/profile
Retrieve the behavioral profile for an identity. Returns the profile summary and session history. Requires Authorization: Bearer <jwt> header.
/dashboard/alerts
List sessions that triggered a review or mismatch alert. Enriched with session and account context. Supports filtering by account_id and pagination. Requires Authorization: Bearer <jwt> header.
Webhooks
Webhook Events
session.completed
Fired when a session is marked as completed. Payload includes the full session object.
analysis.completed
Fired when analysis finishes for a session. Payload includes the full analysis result.
signal.alert
Fired when analysis produces a match score below the match threshold. Replaces analysis.completed for that webhook.
If a secret is configured, payloads include an X-Stradum-Signature header with an HMAC-SHA256 signature for verification.
/webhooks
Register a new webhook endpoint. Requires X-Stradum-Key header with a secret key (sk_live_).
Request Body
| Field | Type | Description |
|---|---|---|
| url | string | Required. HTTPS endpoint URL to receive events. |
| events | string[] | Required. Array of event types to subscribe to. |
| secret | string? | Shared secret for HMAC-SHA256 signing |
curl -X POST https://api.stradum.com/api/v1/webhooks \
-H "Content-Type: application/json" \
-H "X-Stradum-Key: sk_live_your_secret_key" \
-d '{
"url": "https://your-server.com/webhooks/stradum",
"events": ["session.completed", "analysis.completed", "signal.alert"],
"secret": "whsec_your_signing_secret"
}'
/webhooks
List all configured webhooks. Returns webhook IDs, URLs, subscribed events, and active status. Requires X-Stradum-Key header with a secret key (sk_live_).
/webhooks/{"{webhook_id}"}
Delete a webhook configuration. Returns 204 No Content on success. Requires X-Stradum-Key header with a secret key (sk_live_).
Schema Reference
SessionResponse
| Field | Type | Description |
|---|---|---|
| session_id | string | Unique session identifier |
| identity_id | string? | Linked identity ID (null if unlinked) |
| account_id | string? | Associated account ID |
| account_name | string? | Human-readable account name |
| status | string | active, completed, analyzed, abandoned, expired, rejected |
| match_status | string? | match, review, mismatch |
| match_score | float? | Similarity score 0–100 (higher = more similar) |
| created_at | datetime | Session creation timestamp |
| updated_at | datetime | Last update timestamp |
| completed_at | datetime? | Completion timestamp |
| event_count | int | Total ingested events |
| metadata | object | Custom key-value metadata |
| device_info | object | Device fingerprint data |
| field_values | object | Submitted field name → value map |
IdentityResponse
| Field | Type | Description |
|---|---|---|
| identity_id | string | Stradum identity ID |
| external_id | string? | Your internal user/person ID |
| account_ids | string[] | Associated account IDs |
| created_at | datetime | Identity creation timestamp |
| session_count | int | Number of linked sessions |
| metadata | object | Custom metadata |
ScoreResponse
Returned by GET /analysis/session/{session_id}/score and POST /analysis/trigger.
| Field | Type | Description |
|---|---|---|
| session_id | string | Analyzed session |
| identity_id | string | Identity used for baseline |
| analyzed_at | datetime | Analysis timestamp |
| result.score | float | Similarity score 0–100 (72+ = match, 40–72 = review, <40 = mismatch) |
| result.match_status | string | match, review, or mismatch |
| result.confidence | float | Confidence level 0.0–1.0 (grows with more baseline sessions) |
| signals | string[] | High-level behavioral signal categories that contributed to the score |
| reasons | Reason[] | Human-readable explanations for the score |
| context.baseline_sessions | int | Number of prior sessions in the baseline |
| context.summary | string | Human-readable analysis summary |
Reason
| Field | Type | Description |
|---|---|---|
| code | string | Machine-readable reason code |
| category | string | Behavioral category (e.g. typing, mouse, navigation) |
| severity | string | none, mild, moderate, severe |
| description | string | Human-readable explanation |
AlertItem
| Field | Type | Description |
|---|---|---|
| analysis_id | string | Analysis that triggered the alert |
| session_id | string | Flagged session |
| identity_id | string | Identity involved |
| account_id | string? | Associated account |
| account_name | string? | Account name |
| analyzed_at | datetime | When analysis ran |
| match_score | float | Similarity score |
| match_status | string | review or mismatch |
| confidence | float | Confidence level |
| summary | string | Human-readable alert summary |
| reasons | Reason[] | What triggered the alert |
| session_created_at | datetime? | When the session started |
| event_count | int | Session event count |
WebhookResponse
| Field | Type | Description |
|---|---|---|
| webhook_id | string | Unique webhook ID |
| url | string | Delivery endpoint URL |
| events | string[] | Subscribed event types |
| active | boolean | Whether the webhook is active |
| created_at | datetime | Registration timestamp |
Changelog
A running log of new features, improvements, and fixes shipped to the Stradum platform.
- +Scoring engine calibration — variance floor, dynamic z-score thresholds, baseline-aware match status classification, and volatile signal downweighting eliminate false positives during early baseline building
- +Absolute red-flag detection — paste into identity fields, automation signals, and window-switching patterns override lenient early-session thresholds
- +Match statuses simplified to three:
match,review,mismatch - +New
/scoreand/detailendpoints with five signal categories and plain-language reason codes - +Session Timeline replaces raw event replay — abstracted, server-rendered visualization
- +Four-tier authentication model — Public, SDK Key (
pk_live_), Server Key (sk_live_), Superadmin JWT - +IP protection overhaul — raw events, feature vectors, and internal data removed from all customer-facing endpoints
- +MCP Server section added to API documentation with setup instructions
- +Downloadable OpenAPI 3.0.3 spec and Postman collection
- +Graduated usage-based pricing with volume discounts, interactive cost calculator, and optional add-ons
- +30-day free pilot with all features unlocked (up to 1,500 sessions)
- ~API header renamed from
X-BS-KeytoX-Stradum-Key - ~Environment variable prefix changed from
BS_toSTM_ - ~Entity IDs now prefixed with
stm_(sessions, identities, analyses) - ~Confidence score now honestly reflects baseline depth (0.30 at baseline 0 → 0.90 at baseline 6+)
- !Removed unauthenticated "open mode" fallback — all endpoints now require at minimum a publishable key
- !Removed raw event replay endpoint from customer-facing API
- +Quick Start integration guide on the Settings page with auto-populated API keys
- +Publishable API keys are now fully visible and copyable in the dashboard
- +Background session auto-expiry — stale active sessions are automatically expired after 30 min idle or 60 min total
- +Match score now displayed inline next to the match status badge across all views
- +Changelog section added to API documentation
- +Multi-tenant architecture with organization-scoped data isolation
- +Publishable & secret API key pairs for SDK and server-to-server auth
- +JWT-based dashboard authentication replacing legacy admin key
- +10 new
/api/v1/auth/*endpoints — register, login, key management, team management - +Settings page with API key management and team member controls
- ~SDK updated to send
X-Stradum-Keyheader — SDK v1.1.0 - +Migration script for existing single-tenant deployments
- +Marketing landing page and comprehensive API documentation site
- +Dashboard deployed as standalone Railway service
- +Dashboard admin key gate and session-based logout
- +Fixed sidebar layout — non-scrolling, persistent navigation
- ~CORS configuration updated for multi-service architecture
- ~OPTIONS preflight requests now bypass auth middleware
- !Fixed SDK bundle blocked by dashboard auth middleware
- +Initial release — API v1, SDK v1.0.0
- +Session lifecycle — create, ingest events, complete
- +Identity resolution and cross-session linking
- +Behavioral analysis engine with scoring and behavioral assessment
- +Real-time webhook delivery for analysis events
- +JavaScript SDK with automatic form instrumentation
- +React dashboard with session explorer, alerts, and identity profiles
- +PostgreSQL and in-memory storage backends