[{"data":1,"prerenderedAt":292},["ShallowReactive",2],{"blog-stories/api-abuse-costs":3},{"id":4,"title":5,"body":6,"category":272,"date":273,"dateModified":274,"description":275,"draft":276,"extension":277,"faq":278,"featured":276,"headerVariant":272,"image":278,"keywords":278,"meta":279,"navigation":280,"ogDescription":281,"ogTitle":278,"path":282,"readTime":278,"schemaOrg":283,"schemaType":284,"seo":285,"sitemap":286,"stem":287,"tags":288,"twitterCard":290,"__hash__":291},"blog/blog/stories/api-abuse-costs.md","How API Abuse Nearly Bankrupted a Developer Tools Startup",{"type":7,"value":8,"toc":265},"minimark",[9,16,19,24,44,47,53,57,65,75,78,91,94,115,119,122,125,139,142,146,152,155,182,206,228,257],[10,11,12],"tldr",{},[13,14,15],"p",{},"Someone discovered a developer tools company's /api/generate endpoint had no authentication or rate limiting. Over a weekend, they made millions of requests using the company's OpenAI API key. The team woke up Monday to a $47,000 bill. After lengthy negotiations, OpenAI forgave most of the charges, but only after the team proved they'd implemented proper protections.",[13,17,18],{},"On Monday morning, the founder of a small developer tools company opened an email from OpenAI with the subject line \"Usage Alert - Action Required.\" The number inside made him physically ill.",[20,21,23],"h2",{"id":22},"the-horrifying-discovery","The Horrifying Discovery",[25,26,27,32,36,40],"stat-grid",{},[28,29],"stat-card",{"label":30,"number":31},"OpenAI charges","$47K",[28,33],{"label":34,"number":35},"API requests","3.2M",[28,37],{"label":38,"number":39},"Duration","48 hrs",[28,41],{"label":42,"number":43},"Normal monthly bill","$500",[13,45,46],{},"The company's typical OpenAI bill was $500/month. That weekend had generated nearly 100x that amount. Someone had found the AI endpoint and used it as their personal GPT-4 server.",[48,49,50],"story-block",{},[13,51,52],{},"\"The founder remembers sitting in his car in the parking lot, unable to go into the office. The company had maybe $20K in the bank. This bill alone would wipe them out and then some.\"",[20,54,56],{"id":55},"how-they-found-the-endpoint","How They Found the Endpoint",[13,58,59,60,64],{},"The company had built an AI-powered code documentation tool. The frontend sent requests to ",[61,62,63],"code",{},"/api/generate"," which proxied to OpenAI. Simple, clean, and completely unprotected.",[66,67,72],"pre",{"className":68,"code":70,"language":71},[69],"language-text","// The original (terrible) endpoint\napp.post('/api/generate', async (req, res) => {\n  const { prompt } = req.body;\n\n  // No auth check. No rate limit. Just vibes.\n  const completion = await openai.chat.completions.create({\n    model: \"gpt-4\",\n    messages: [{ role: \"user\", content: prompt }]\n  });\n\n  res.json(completion);\n});\n","text",[61,73,70],{"__ignoreMap":74},"",[13,76,77],{},"The attacker probably found the endpoint through:",[79,80,81,85,88],"ul",{},[82,83,84],"li",{},"Scanning JavaScript bundles for API endpoints",[82,86,87],{},"Checking network requests in browser dev tools",[82,89,90],{},"Automated scanners looking for unprotected AI endpoints",[13,92,93],{},"Once they found a working endpoint, they set up a script to pump through requests 24/7.",[95,96,98],"warning-box",{"title":97},"The Company's Mistakes",[79,99,100,103,106,109,112],{},[82,101,102],{},"No authentication required to use the endpoint",[82,104,105],{},"No rate limiting whatsoever",[82,107,108],{},"No usage caps or spending alerts set up",[82,110,111],{},"No monitoring for unusual usage patterns",[82,113,114],{},"Using GPT-4 (expensive) instead of GPT-3.5 where appropriate",[20,116,118],{"id":117},"the-recovery","The Recovery",[13,120,121],{},"The founder immediately rotated the API key to stop the bleeding. Then began the painful process of dealing with the bill.",[13,123,124],{},"OpenAI support was understanding but needed assurance this wouldn't happen again. The team documented everything:",[79,126,127,130,133,136],{},[82,128,129],{},"Proof that requests came from unknown IPs, not their users",[82,131,132],{},"The new authentication and rate limiting implementation",[82,134,135],{},"Spending alerts configured at multiple thresholds",[82,137,138],{},"Monthly spending caps enabled",[13,140,141],{},"After two weeks of back-and-forth, OpenAI forgave $42,000 of the charges. The company still paid $5,000, which was painful but survivable.",[20,143,145],{"id":144},"the-fix","The Fix",[66,147,150],{"className":148,"code":149,"language":71},[69],"// The secure version\nimport { rateLimit } from 'express-rate-limit';\nimport { authMiddleware } from './auth';\n\nconst aiLimiter = rateLimit({\n  windowMs: 60 * 1000, // 1 minute\n  max: 10, // 10 requests per minute per user\n  message: 'Too many requests, please slow down'\n});\n\napp.post('/api/generate',\n  authMiddleware,        // Require login\n  aiLimiter,             // Rate limit\n  usageTracker,          // Track per-user usage\n  async (req, res) => {\n    const user = req.user;\n\n    // Check user's remaining quota\n    if (user.aiCredits \u003C= 0) {\n      return res.status(403).json({\n        error: 'Usage limit reached'\n      });\n    }\n\n    // Process request...\n    await decrementUserCredits(user.id);\n});\n",[61,151,149],{"__ignoreMap":74},[13,153,154],{},"The team also set up proper OpenAI spending controls:",[79,156,157,164,170,176],{},[82,158,159,163],{},[160,161,162],"strong",{},"Hard spending cap",": $1,000/month maximum",[82,165,166,169],{},[160,167,168],{},"Email alerts",": At $100, $300, $500, $800",[82,171,172,175],{},[160,173,174],{},"Daily monitoring",": Automated checks for unusual spikes",[82,177,178,181],{},[160,179,180],{},"Per-user limits",": Maximum requests per user per day",[183,184,186],"lesson-box",{"title":185},"Key Lessons Learned",[79,187,188,191,194,197,200,203],{},[82,189,190],{},"Always authenticate API endpoints, especially ones that cost money",[82,192,193],{},"Implement rate limiting on all public-facing endpoints",[82,195,196],{},"Set spending caps and alerts with your API providers",[82,198,199],{},"Track per-user usage to catch abuse early",[82,201,202],{},"Use the cheapest appropriate model for each task",[82,204,205],{},"Monitor for unusual patterns - weekend spikes should trigger alerts",[207,208,209,216,222],"faq-section",{},[210,211,213],"faq-item",{"question":212},"Will OpenAI forgive fraudulent charges?",[13,214,215],{},"They evaluate case by case. You'll need to prove it was abuse (not legitimate usage), show what security measures you've implemented, and work with their support team. They're generally understanding but don't guarantee forgiveness.",[210,217,219],{"question":218},"How do attackers find unprotected AI endpoints?",[13,220,221],{},"They scan JavaScript bundles for API routes, monitor network traffic on popular AI apps, use automated scanners, and share discovered endpoints in underground communities. If your endpoint is public and unprotected, assume it will be found.",[210,223,225],{"question":224},"What's a reasonable rate limit for AI endpoints?",[13,226,227],{},"It depends on your use case, but for most apps: 10-20 requests per minute per authenticated user is reasonable. For anonymous/trial users, consider 3-5 requests per hour. Always combine with authentication and per-user quotas.",[229,230,231,237,242,247,252],"related-articles",{},[232,233],"related-card",{"description":234,"href":235,"title":236},"The emotional journey of dealing with security as a solo founder. The overwhelm, the near-surrender, and how I found a s","/blog/stories/almost-gave-up","Why I Almost Gave Up on Security",[232,238],{"description":239,"href":240,"title":241},"A founder's story of discovering their Stripe secret key was exposed in a public GitHub repo. The panic, the response, a","/blog/stories/api-key-leaked-stripe","When My Stripe API Key Got Leaked",[232,243],{"description":244,"href":245,"title":246},"How an exposed AWS credential led to a cryptocurrency mining operation on my account. The shocking bill, the investigati","/blog/stories/aws-bill-crypto","The $12,000 AWS Bill That Changed Everything",[232,248],{"description":249,"href":250,"title":251},"A stranger found a health-tech startup's admin panel at /admin with no authentication. They could see all patient data, ","/blog/stories/admin-panel-found","When Someone Found a Health-Tech Startup's Unprotected Admin Panel",[232,253],{"description":254,"href":255,"title":256},"In early 2025, AI-assisted attackers compromised 50,000 FortiGate firewalls in weeks. Here's what happened and why it ma","/blog/stories/ai-assisted-fortigate-attack","How Attackers Used AI to Breach 50,000 FortiGate Firewalls",[258,259,262],"cta-box",{"href":260,"label":261},"/","Check Your Vibe Now",[13,263,264],{},"Scan your vibe coded projects for unprotected APIs and missing rate limits.",{"title":74,"searchDepth":266,"depth":266,"links":267},2,[268,269,270,271],{"id":22,"depth":266,"text":23},{"id":55,"depth":266,"text":56},{"id":117,"depth":266,"text":118},{"id":144,"depth":266,"text":145},"stories","2026-01-07","2026-03-16","Someone found a developer tools company's unprotected AI API endpoint and racked up $47,000 in OpenAI charges in a single weekend. The story of how the team discovered and stopped the abuse.",false,"md",null,{},true,"Someone racked up $47,000 in OpenAI charges through a developer tools company's unprotected endpoint.","/blog/stories/api-abuse-costs","[object Object]","BlogPosting",{"title":5,"description":275},{"loc":282},"blog/stories/api-abuse-costs",[289],"Security Story","summary_large_image","_etUCSjBXXo1EdAni5g5IaXqu9fbtrrScKoV12EHQ2w",1775843936807]