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)
Enter fullscreen mode Exit fullscreen mode
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.
--------------------------------------------------
Enter fullscreen mode Exit fullscreen mode
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())
"
Enter fullscreen mode Exit fullscreen mode
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.