Last week I caught myself thinking: "I always mess everything up."
My therapist would recognize this as overgeneralization — a cognitive distortion where one mistake becomes "everything." But I didn't want to wait for my next session to check. So I built a journal that flags distortions automatically, using a free API I deployed myself.
Here's the whole thing in 50 lines.
The API: CBT Thought Analyzer
I deployed a CBT (Cognitive Behavioral Therapy) thought analyzer as a free API. It detects:
- 11 cognitive distortions (catastrophizing, all-or-nothing, overgeneralization, mind reading, fortune telling, should statements, labeling, personalization, etc.)
- 8 procrastination patterns (perfectionism block, fear of failure, task overwhelm, etc.)
- 4 attachment styles (Secure, Preoccupied, Fearful, Dismissing)
No AI model needed — it uses evidence-based keyword pattern matching for instant analysis. Based on David Burns' Feeling Good framework.
Endpoint: https://cbt-thought-analyzer.onrender.com
The Journal: 50 Lines of Python
import requests
from datetime import datetime
import json
BASE_URL = "https://cbt-thought-analyzer.onrender.com"
def analyze_thought(thought: str) -> dict:
"""Send a thought to the CBT analyzer and get distortions back."""
resp = requests.post(f"{BASE_URL}/analyze", json={"text": thought}, timeout=30)
resp.raise_for_status()
return resp.json()
def check_procrastination(description: str) -> dict:
"""Check which procrastination patterns are keeping you stuck."""
resp = requests.post(f"{BASE_URL}/procrastination", json={"text": description}, timeout=30)
resp.raise_for_status()
return resp.json()
def journal_entry(thought: str) -> None:
"""Write a journal entry with automatic CBT analysis."""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
print(f"\n📝 {timestamp}")
print(f"Thought: \"{thought}\"\n")
# Analyze for0 for cognitive distortions
result = analyze_thought(thought)
distortions = result.get("distortions", [])
if distortions:
print("🔍 Detected distortions:")
for d in distortions:
print(f" • {d['name']} (confidence: {d['confidence']}%)")
print(f" → {d['reframe']}")
else:
print("✅ No distortions detected — this thought looks balanced.")
# Check for procrastination patterns
proc = check_procrastination(thought)
patterns = proc.get("patterns", [])
if patterns:
print("\n⏰ Procrastination patterns:")
for p in patterns:
print(f" • {p['name']}: {p['intervention']}")
# --- Daily Journal ---
thoughts = [
"I always mess everything up.",
"I can't start this project until I have the perfect plan.",
"If I fail this presentation, my career is over.",
]
for thought in thoughts:
journal_entry(thought)
print("-" * 50)
What the Output Looks Like
📝 2026-09-19 09:30
Thought: "I always mess everything up."
🔍 Detected distortions:
• Overgeneralization (confidence: 92%)
→ "Always" is a strong word. Can you think of a specific exception?
• Labeling (confidence: 78%)
→ You're labeling yourself based on one event. You are not your mistakes.
⏰ Procrastination patterns:
• All-or-nothing approach: Try breaking the task into smaller steps.
--------------------------------------------------
📝 2026-09-19 09:30
Thought: "I can't start this project until I have the perfect plan."
🔍 Detected distortions:
• Should statements (confidence: 85%)
→ "Can't" until "perfect" is a should statement. What's "good enough"?
• All-or-nothing (confidence: 88%)
→ Perfect vs. not-started is a false binary. What's the middle ground?
⏰ Procrastination patterns:
• Perfectionism block: Start with a rough draft. You can refine later.
• Waiting for motivation: Action precedes motivation, not the other way.
--------------------------------------------------
How It Works
The API uses keyword pattern matching — no AI model, no API key needed for the free tier. Each distortion has a set of linguistic markers:
- Overgeneralization: "always", "never", "every time", "nobody"
- Catastrophizing: "if...then disaster", "what if...terrible"
- Should statements: "should", "must", "have to", "can't until"
- Mind reading: "they think", "everyone knows", "he probably"
When you send a thought, the API matches it against these patterns and returns the distortion name, a confidence score (based on how many markers matched), and a reframe prompt — a question that helps you challenge the distortion.
Why This Is Better Than a Chatbot
- Instant — no waiting for an LLM to generate a response
- Transparent — you can see exactly which keywords triggered the detection
- Free — no API costs, no rate limits on the free tier
- Private — your thoughts aren't sent to an AI company's servers
- Evidence-based — the patterns come from David Burns' Feeling Good, not a model's guess
Try It Yourself
# Test the API with curl
curl -X POST https://cbt-thought-analyzer.onrender.com/analyze \
-H "Content-Type: application/json" \
-d '{"text": "I always fail at everything."}'
# Or with Python
pip install requests
python -c "
import requests
r = requests.post('https://cbt-thought-analyzer.onrender.com/analyze', json={'text': 'I always fail at everything.'})
print(r.json())
"
What's Next
I'm working on:
- A RapidAPI listing so you can subscribe with a single click
- A Python SDK and JavaScript SDK for easier integration
- A Postman collection for testing all endpoints
- An OpenAPI spec for auto-generating clients in any language
The API is open and free to use right now. If you build something with it, let me know in the comments — I'd love to see what you create.
This is part of a CBT toolkit — 24 free mental health tools, all open source.
Top comments (0)