Behavioral intelligence API

Your users feel things.
Now your app
can too.

SessionMood scores user behavior in real time — clicks, hesitations, errors, rage clicks — and returns a mood + a suggested action while the session is still live.

No PII required  ·  GDPR ready  ·  Zero dependencies

session mood api
# 1. Send behavioral events
POST /v1/sessions/u_9x2k/events
{ "events": [
{ "type": "rage_click", "x": 340, "ts": 1000 },
{ "type": "error", "message": "404", "ts": 1001 }
] }

# 2. Get the mood — act on it
GET /v1/sessions/u_9x2k/mood

{
"mood": "frustrated",
"confidence": 0.89,
"suggested_action": "show_live_chat"
}
12
Event types
6
Mood states
<50ms
Response time
0
Dependencies
Free
To start

Three steps. Under 10 minutes.

1

Send events

As your user interacts, POST behavioral events to the API — clicks, scrolls, errors, navigations. Batch them every few seconds.

POST /v1/sessions/:id/events
2

Get a mood

The API scores the session and returns a mood, a confidence score, and the signals it detected — updated after every batch.

GET /v1/sessions/:id/mood
3

Take action

Use suggested_action to trigger the right intervention — live chat, help tooltip, engagement prompt — while the user is still there.

POST /v1/sessions/:id/feedback

Analytics tell you what.
We tell you why — right now.

Traditional tools show you drop-off rates days later. SessionMood gives you a signal while the user is still on the page — in time to actually do something about it.

Real-time signal

Mood is scored after every event batch. Your app knows a user is frustrated before they rage-quit — not in next week's report.

🔌

Dead simple integration

A plain REST API with no SDKs to install. If you can make a fetch request, you can integrate in an afternoon.

🎯

Actionable, not just data

Every response includes a suggested_action. Show a tooltip, open chat, simplify the flow — your app decides what to do with it.

🔒

GDPR ready by design

No PII required. Sessions are anonymous IDs you control. One DELETE call permanently purges all data.

Built for teams who can't afford to lose users at the wrong moment.

E-commerce
Online stores
Detect frustration at checkout before the user abandons. Trigger live chat or simplify the form automatically.
1% conversion lift = thousands/month
SaaS
Product teams
Catch confused new users during onboarding. Surface help or a human at the exact moment they need it.
Reduce churn in the critical first 10 minutes
Agencies
UX agencies
Embed behavioral intelligence in every client project. Show mood heatmaps across user journeys as a new deliverable.
New upsell line item on every project
Platforms
No-code tools
Webflow, Bubble, Framer plugins. One partnership means thousands of end users flowing through you.
Channel multiplier for distribution

Six moods. One clear action each.

frustrated

Rage clicks, repeated errors, rapidly escalating interactions

rage_click_detectedrepeated_errorsfast_scroll
show_live_chat
confused

Backtracking, long pauses, hovering without acting, JS errors

backtrack_detectedhover_hesitationerror_encountered
show_help_tooltip
decisive

Fast, direct, no hesitation, goal-oriented clicking

fast_direct_interactions
reduce_friction
browsing

Wandering scroll, multi-page exploration, no clear destination

multi_page_browsehigh_page_churn
show_recommendations
disengaged

Long idle periods, minimal input, attention has drifted

long_idle
show_engagement_prompt
focused

Steady, moderate pace, task-oriented, deep in flow state

steady_interaction_pattern
stay_out_of_the_way

12 event types. All accepted.

Send any combination of these in a single events array. The more signals you send, the more accurate the mood score.

click

Click

User clicked an element. Fields: x, y, ts

→ decisive (rapid bursts)
rage_click

Rage click

Rapid repeated clicks on the same target. Fields: x, y, ts

→ frustrated (strong signal)
scroll

Scroll

User scrolled the page. Fields: speed, direction, ts

→ frustrated (fast) · focused (steady)
input_pause

Input pause

User paused while typing. Fields: duration_ms, ts

→ confused (pauses ≥ 2.5s)
backtrack

Backtrack

User reversed an in-app action. Fields: ts

→ confused
back_nav

Back navigation

User hit the browser back button. Fields: ts

→ confused
page_view

Page view

User navigated to a new page. Fields: url, ts

→ browsing (2+) · confused (4+, high churn)
error

Error

A JS or app error occurred. Fields: message, ts

→ confused (1) · frustrated (2+)
idle

Idle

No activity detected. Fields: duration_ms, ts

→ disengaged (≥ 10s)
hover

Hover

User hovering over an element. Fields: duration_ms, ts

→ browsing · hesitation
focus

Focus

An input or element received focus. Fields: ts

→ engagement signal
blur

Blur

An input or element lost focus. Fields: ts

→ engagement signal

Copy. Paste. Done.

// No package needed — plain fetch API
const API_KEY = 'your_api_key_here';
const BASE    = 'https://session-mood-api-production.up.railway.app/v1';
const SESSION = 'user_abc123';  // any unique ID for this session

// 1. Send events as the user interacts
await fetch(`${BASE}/sessions/${SESSION}/events`, {
  method: 'POST',
  headers: { 'X-Api-Key': API_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({ events: [
    { type: 'page_view', url: '/checkout', ts: Date.now() / 1000 },
    { type: 'rage_click', x: 340, y: 210, ts: Date.now() / 1000 },
    { type: 'error', message: 'Payment failed', ts: Date.now() / 1000 }
  ]})
});

// 2. Get the mood — act on it
const mood = await fetch(`${BASE}/sessions/${SESSION}/mood`, {
  headers: { 'X-Api-Key': API_KEY }
}).then(r => r.json());

// mood.mood             → "frustrated"
// mood.confidence       → 0.89
// mood.suggested_action → "show_live_chat"

if (mood.mood === 'frustrated') openLiveChat();
if (mood.mood === 'confused')   showHelpTooltip();
if (mood.mood === 'disengaged') showEngagementPrompt();
# pip install requests
import requests, time

API_KEY = "your_api_key_here"
BASE    = "https://session-mood-api-production.up.railway.app/v1"
SESSION = "user_abc123"
HEADERS = {"X-Api-Key": API_KEY}

# 1. Send events
requests.post(f"{BASE}/sessions/{SESSION}/events",
  headers=HEADERS,
  json={"events": [
    {"type": "page_view",  "url": "/checkout",        "ts": time.time()},
    {"type": "rage_click", "x": 340, "y": 210,           "ts": time.time()},
    {"type": "error",      "message": "Payment failed", "ts": time.time()},
  ]}
)

# 2. Get mood and act
mood = requests.get(f"{BASE}/sessions/{SESSION}/mood",
  headers=HEADERS
).json()

print(mood["mood"])             # "frustrated"
print(mood["confidence"])       # 0.89
print(mood["suggested_action"])  # "show_live_chat"
# 1. Send events
curl -X POST https://session-mood-api-production.up.railway.app/v1/sessions/user_abc/events \
  -H "X-Api-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      { "type": "page_view",  "url": "/checkout",       "ts": 1714900200 },
      { "type": "rage_click", "x": 340, "y": 210,       "ts": 1714900201 },
      { "type": "error",      "message": "Payment failed","ts": 1714900202 }
    ]
  }'

# 2. Get mood
curl https://session-mood-api-production.up.railway.app/v1/sessions/user_abc/mood \
  -H "X-Api-Key: your_api_key_here"

# Response:
{
  "mood": "frustrated",
  "confidence": 0.89,
  "signals": ["rage_click_detected", "repeated_errors"],
  "suggested_action": "show_live_chat"
}

Start free. Pay as you grow.

Starter
Free
5,000 sessions / month, forever
  • API key access
  • All 12 event types
  • All 6 mood states
  • 7-day data retention
  • Community support
Get your free key
Pro
$99
/ month · +$0.0008 per session after 200k
  • 200,000 sessions / month
  • Feedback loop training
  • Webhook support
  • 90-day retention
  • Priority support
  • SLA guarantee
Start Pro plan

Common questions.

Any string that uniquely identifies a user session — your own session token, a user ID, or a UUID you generate on page load. Keep it consistent across events so they all land in the same session. You never send actual user data to us.
Add event listeners in your frontend JavaScript for the interactions you care about (clicks, scroll, errors via window.onerror, navigation via popstate), then POST them to our API in batches every few seconds. You're in full control of what you track and send.
You'll get a result after 2+ events, though confidence will be low. The score stabilizes noticeably around 5–10 events. For most sessions, you'll have a reliable mood within the first 30 seconds of interaction.
Yes. We require no PII — session IDs are opaque strings you control. All event data is behavioral (coordinates, timings, types), not personal. One DELETE call permanently removes all data for a session. You decide retention period.
Yes — SessionMood is listed on RapidAPI. Search "SessionMood" to connect with a RapidAPI key. The free tier is the same: 5,000 sessions per month.