DEV Community

Cover image for I built a REST API that detects how your users feel in real time
Bendrot Studios
Bendrot Studios

Posted on

I built a REST API that detects how your users feel in real time

I got tired of not knowing why users were dropping off in my app. Heatmaps show you where people click. Analytics show you when they leave. But nothing tells you how they felt while using it.

So I built SessionMood API — a REST API that scores user mood in real time based on behavioral events.

How it works

You send behavioral events from your frontend:

fetch("https://session-mood-api-production.up.railway.app/v1/sessions/user_123/events", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "YOUR_API_KEY"
  },
  body: JSON.stringify({ type: "click" })
});
Enter fullscreen mode Exit fullscreen mode

Then read the mood at any point:

fetch("https://session-mood-api-production.up.railway.app/v1/sessions/user_123/mood", {
  headers: { "x-api-key": "YOUR_API_KEY" }
})
.then(r => r.json())
.then(console.log);
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "mood": "frustrated",
  "confidence": 0.85,
  "suggested_action": "offer_help",
  "signals": ["rage_click", "high_error_rate"],
  "event_count": 12
}
Enter fullscreen mode Exit fullscreen mode

Supported event types

  • click — regular click
  • rage_click — multiple rapid clicks on the same element
  • scroll — scroll depth (pass value 0-100)
  • idle — user stopped interacting
  • page_view — new page loaded
  • error — JS error or failed request
  • hover, focus, blur, copy, paste, navigation

The 6 mood states

Mood Signals
frustrated rage clicks, errors
engaged active clicks, deep scrolls
bored long idle, minimal interaction
confused repeated actions, back-and-forth
curious exploratory scrolling, hovering
satisfied smooth session, positive signals

What I used to build it

  • Node.js — plain HTTP server, zero frameworks
  • Supabase — Postgres for session storage and API key management
  • Railway — deployment, spins up in seconds
  • No SDKs — just fetch() calls

The whole scoring engine is a weighted signal system. Each event type adds or subtracts from mood scores across all 6 states. The highest score wins.

Try it free

It's live on RapidAPI with a free tier (5,000 sessions/month):
https://rapidapi.com/angelobendrot/api/sessionmood

Full docs:
https://session-mood-api.netlify.app/docs.html

Would love to hear what behavioral signals you think matter most for detecting user mood. Drop a comment below!

Top comments (2)

Collapse
 
djims_001 profile image
DJims

The weighted signal scoring approach is genuinely clever here. Most behavioral analytics tools treat events as counters, but mapping them across 6 competing mood states simultaneously and taking the highest score is a much more nuanced model. Curious how you tuned the weights — was it empirical testing, or more intuition-driven at this stage?

One edge case I'd think about: rage clicks can sometimes indicate enthusiasm on a slow-loading element rather than frustration (e.g. a user eagerly clicking a "submit" button that hasn't responded yet). Do you differentiate based on whether an error event follows shortly after, or is the signal purely based on click frequency?

The zero-framework Node.js choice is refreshing. A lot of people reach for Express reflexively — plain HTTP keeps the surface area small and the latency predictable, which matters a lot when you're ingesting high-frequency behavioral events per session.
I could see this being really powerful combined with session replay tools — you'd know when a user got frustrated, and the replay would show you exactly what caused it.

Going to check out the RapidAPI listing. Nice work shipping something concrete here.

Collapse
 
bendrotstudios profile image
Bendrot Studios

Thanks for the thoughtful breakdown — these are exactly
the kinds of edge cases I've been thinking about.

On the weights: honestly, it's intuition-driven at this
stage. I started with reasonable assumptions (rage clicks
= frustration, deep scrolls = curiosity) and iterated
from there. The plan is to use the feedback endpoint
(/v1/sessions/:id/feedback) to collect corrections over
time and tune the weights empirically with real data.

You're spot on about rage clicks. Right now the signal
is purely frequency-based, but I'm planning to add
temporal correlation — if a rage_click is followed by
an error event within a short window, it weights much
more heavily toward frustrated. If no error follows,
it stays more neutral.

The session replay integration idea is something I've
thought about too — combining SessionMood with something
like LogRocket or rrweb so you can jump straight to the
moment frustration spiked would be really powerful.

Appreciate you checking out the RapidAPI listing —
would love to hear what you think after trying it.