[{"data":1,"prerenderedAt":441},["ShallowReactive",2],{"blog-how-to/rotate-api-keys":3},{"id":4,"title":5,"body":6,"category":422,"date":423,"dateModified":423,"description":424,"draft":425,"extension":426,"faq":427,"featured":425,"headerVariant":428,"image":427,"keywords":427,"meta":429,"navigation":430,"ogDescription":431,"ogTitle":427,"path":432,"readTime":427,"schemaOrg":433,"schemaType":434,"seo":435,"sitemap":436,"stem":437,"tags":438,"twitterCard":439,"__hash__":440},"blog/blog/how-to/rotate-api-keys.md","How to Rotate API Keys - Emergency Response Guide",{"type":7,"value":8,"toc":402},"minimark",[9,13,17,22,25,31,40,45,64,68,87,126,149,170,180,201,205,209,230,233,237,255,258,262,283,289,293,309,313,316,342,364,383],[10,11],"category-badge",{"category":12},"How-To Guide",[14,15,16],"p",{},"Emergency Response",[18,19,21],"h1",{"id":20},"how-to-rotate-api-keys","How to Rotate API Keys",[14,23,24],{},"Emergency guide for when your keys are compromised",[26,27,28],"tldr",{},[14,29,30],{},"TL;DR:\nGenerate a new key immediately, update it in your hosting platform's environment variables, deploy, then revoke the old key. Don't try to remove it from git history first. Speed matters more than cleanup when credentials are exposed.",[32,33,34,37],"warning-box",{},[14,35,36],{},"Time is Critical",[14,38,39],{},"Every minute a compromised key stays active is a minute an attacker can use it. API abuse can rack up thousands in charges within hours. Follow these steps immediately.",[41,42,44],"h2",{"id":43},"quick-action-checklist","Quick Action Checklist",[46,47,48,52,55,58,61],"ol",{},[49,50,51],"li",{},"Generate new key in service dashboard (2 minutes)",[49,53,54],{},"Update environment variable in hosting platform (2 minutes)",[49,56,57],{},"Trigger a redeploy (1-5 minutes)",[49,59,60],{},"Revoke/delete the old key (1 minute)",[49,62,63],{},"Check logs for unauthorized usage (after securing)",[41,65,67],{"id":66},"step-by-step-guide","Step-by-Step Guide",[69,70,72,77,80],"step",{"number":71},"1",[73,74,76],"h3",{"id":75},"generate-a-new-api-key","Generate a new API key",[14,78,79],{},"Go to the affected service's dashboard and create a new key. Most services let you have multiple active keys, so you can create the new one before revoking the old one.",[14,81,82,86],{},[83,84,85],"strong",{},"Do not delete the old key yet."," Your production app is still using it.",[69,88,90,94,97,118],{"number":89},"2",[73,91,93],{"id":92},"update-your-production-environment","Update your production environment",[14,95,96],{},"Update the environment variable in your hosting platform:",[98,99,100,106,112],"ul",{},[49,101,102,105],{},[83,103,104],{},"Vercel:"," Project Settings → Environment Variables → Edit → Save",[49,107,108,111],{},[83,109,110],{},"Netlify:"," Site Settings → Environment Variables → Edit → Save",[49,113,114,117],{},[83,115,116],{},"Railway:"," Service → Variables → Update value",[14,119,120,121,125],{},"Also update your local ",[122,123,124],"code",{},".env.local"," file with the new key.",[69,127,129,133,136,146],{"number":128},"3",[73,130,132],{"id":131},"redeploy-your-application","Redeploy your application",[14,134,135],{},"Most platforms pick up environment variable changes on the next deploy:",[137,138,143],"pre",{"className":139,"code":141,"language":142},[140],"language-text","# Vercel - trigger redeploy\nvercel --prod\n\n# Or push an empty commit\ngit commit --allow-empty -m \"Rotate API keys\"\ngit push\n","text",[122,144,141],{"__ignoreMap":145},"",[14,147,148],{},"Some platforms (like Railway) apply changes automatically without redeploying.",[69,150,152,156,159],{"number":151},"4",[73,153,155],{"id":154},"verify-the-new-key-is-working","Verify the new key is working",[14,157,158],{},"Test your production site to confirm the new key is active:",[98,160,161,164,167],{},[49,162,163],{},"Make a request that uses the API key",[49,165,166],{},"Check your application logs for errors",[49,168,169],{},"Verify the feature works as expected",[69,171,173,177],{"number":172},"5",[73,174,176],{"id":175},"revoke-the-compromised-key","Revoke the compromised key",[14,178,179],{},"Only after confirming production works, delete or disable the old key in the service dashboard. The compromised key should no longer work anywhere.",[69,181,183,187,190],{"number":182},"6",[73,184,186],{"id":185},"check-for-unauthorized-usage","Check for unauthorized usage",[14,188,189],{},"Review the service's logs or usage dashboard for suspicious activity:",[98,191,192,195,198],{},[49,193,194],{},"Unusual API call volume",[49,196,197],{},"Requests from unknown IP addresses",[49,199,200],{},"Unexpected charges or usage patterns",[41,202,204],{"id":203},"service-specific-instructions","Service-Specific Instructions",[73,206,208],{"id":207},"stripe","Stripe",[46,210,211,214,217,224,227],{},[49,212,213],{},"Go to Developers → API Keys",[49,215,216],{},"Click \"Create secret key\" (you can name it for tracking)",[49,218,219,220,223],{},"Update ",[122,221,222],{},"STRIPE_SECRET_KEY"," in your hosting platform",[49,225,226],{},"Redeploy",[49,228,229],{},"Click \"...\" next to old key → \"Roll key\" or delete it",[14,231,232],{},"Check Dashboard → Logs for any unauthorized transactions.",[73,234,236],{"id":235},"openai","OpenAI",[46,238,239,242,245,250,252],{},[49,240,241],{},"Go to platform.openai.com → API Keys",[49,243,244],{},"Click \"Create new secret key\"",[49,246,219,247,223],{},[122,248,249],{},"OPENAI_API_KEY",[49,251,226],{},[49,253,254],{},"Delete the old key",[14,256,257],{},"Check Usage page for unexpected API calls. Consider setting a usage limit.",[73,259,261],{"id":260},"supabase","Supabase",[46,263,264,267,270,280],{},[49,265,266],{},"Go to Project Settings → API",[49,268,269],{},"For anon/service_role keys: You'll need to regenerate via \"Generate new keys\"",[49,271,272,273,276,277],{},"Update both ",[122,274,275],{},"SUPABASE_ANON_KEY"," and ",[122,278,279],{},"SUPABASE_SERVICE_ROLE_KEY",[49,281,282],{},"Redeploy all services using these keys",[14,284,285,288],{},[83,286,287],{},"Note:"," Regenerating Supabase keys affects ALL keys at once.",[73,290,292],{"id":291},"firebase","Firebase",[46,294,295,298,301,304,306],{},[49,296,297],{},"Go to Project Settings → Service Accounts",[49,299,300],{},"Click \"Generate new private key\"",[49,302,303],{},"Update the JSON credentials in your hosting platform",[49,305,226],{},[49,307,308],{},"There's no way to revoke old service account keys in Firebase; consider creating a new service account",[41,310,312],{"id":311},"after-the-emergency","After the Emergency",[14,314,315],{},"Once your keys are rotated and secured:",[46,317,318,324,330,336],{},[49,319,320,323],{},[83,321,322],{},"Investigate how the leak happened"," - Check git history, review recent commits",[49,325,326,329],{},[83,327,328],{},"Set up preventive measures"," - Enable GitHub secret scanning, add pre-commit hooks",[49,331,332,335],{},[83,333,334],{},"Document the incident"," - Note the timeline and any impact for future reference",[49,337,338,341],{},[83,339,340],{},"Review other keys"," - If one key leaked, others might have too",[343,344,345,352,358],"faq-section",{},[346,347,349],"faq-item",{"question":348},"Should I try to remove the key from git history?",[14,350,351],{},"Not as your first step. Once a key hits a public repo, assume it's been scraped within minutes. Rotate the key first, then worry about cleaning history if needed. Cleaning history is complicated and time-consuming.",[346,353,355],{"question":354},"How long does it take for attackers to find exposed keys?",[14,356,357],{},"Automated scanners monitor GitHub in real-time. Studies show compromised AWS keys get used within 5 minutes of being pushed. Act immediately.",[346,359,361],{"question":360},"What if I can't redeploy right away?",[14,362,363],{},"If you have access to the service dashboard but can't redeploy, you may need to temporarily disable the API key and accept downtime. A few minutes of downtime is better than hours of unauthorized access.",[14,365,366,369,374,375,374,379],{},[83,367,368],{},"Related guides:",[370,371,373],"a",{"href":372},"/blog/how-to/hide-api-keys","How to Hide API Keys"," ·\n",[370,376,378],{"href":377},"/blog/how-to/check-exposed-keys","How to Check for Exposed Keys",[370,380,382],{"href":381},"/blog/how-to/secret-scanning","How to Enable Secret Scanning",[384,385,386,392,397],"related-articles",{},[387,388],"related-card",{"description":389,"href":390,"title":391},"Step-by-step guide to rate limiting authentication endpoints. Prevent brute force attacks, credential stuffing, and acco","/blog/how-to/rate-limiting-auth","How to Implement Rate Limiting for Authentication",[387,393],{"description":394,"href":395,"title":396},"Clean secrets from your git history after accidental commits. Learn to use BFG Repo Cleaner and git filter-branch to rem","/blog/how-to/remove-secrets-git-history","How to Remove Secrets from Git History",[387,398],{"description":399,"href":400,"title":401},"Step-by-step guide to sanitizing user input. HTML sanitization, XSS prevention with DOMPurify, server-side sanitization,","/blog/how-to/sanitize-input","How to Sanitize User Input",{"title":145,"searchDepth":403,"depth":403,"links":404},2,[405,406,415,421],{"id":43,"depth":403,"text":44},{"id":66,"depth":403,"text":67,"children":407},[408,410,411,412,413,414],{"id":75,"depth":409,"text":76},3,{"id":92,"depth":409,"text":93},{"id":131,"depth":409,"text":132},{"id":154,"depth":409,"text":155},{"id":175,"depth":409,"text":176},{"id":185,"depth":409,"text":186},{"id":203,"depth":403,"text":204,"children":416},[417,418,419,420],{"id":207,"depth":409,"text":208},{"id":235,"depth":409,"text":236},{"id":260,"depth":409,"text":261},{"id":291,"depth":409,"text":292},{"id":311,"depth":403,"text":312},"how-to","2026-01-21","Emergency guide for rotating compromised API keys without downtime. Step-by-step instructions for Stripe, OpenAI, Supabase, and other common services.",false,"md",null,"yellow",{},true,"Emergency guide for rotating compromised API keys without downtime.","/blog/how-to/rotate-api-keys","[object Object]","HowTo",{"title":5,"description":424},{"loc":432},"blog/how-to/rotate-api-keys",[],"summary_large_image","y4ojV-Olt95erL3tVPaPGStQGk4R6ND1TvTlajudz2o",1775843927976]