Deleting a Twilio API key revokes that credential immediately. Closing a subaccount is permanent and irreversible. People search for one and sometimes do the other, which is a bad afternoon.
There are three distinct things people mean by deactivating Twilio access: revoking a credential, suspending a subaccount, and closing one for good. They have very different reversibility, and it is worth being certain which you want before clicking anything.
Table of contents
- Deleting an API key
- Suspending versus closing a subaccount
- Before you close anything
- Auditing what exists
- Keeping credentials manageable
- How this fits the rest of the stack
- FAQ
Deleting an API key
This is the routine operation - rotating a credential, or revoking one that leaked.
- In the console, open the account management area and find the page for auth tokens and API keys.
- Select the key you want to remove.
- Delete it and confirm.
The effect is immediate. Any request using that key SID and secret starts failing with an authentication error the moment it is gone, so anything still holding it breaks straight away.
Which means the order matters. Create the replacement first, deploy it everywhere, verify traffic is flowing on the new credential, and only then delete the old one. Deleting first and scrambling to update services is how a rotation becomes an outage.
- Create a new key and copy the secret - it is shown once.
- Update the credential wherever it is held: the deployment platform’s environment variables, CI secrets, any worker or scheduled job.
- Redeploy and confirm the services are authenticating successfully.
- Check that nothing is still using the old key.
- Delete the old key.
Note the distinction between an API key and the main account auth token. A key can be deleted freely. The auth token is the account’s primary credential, and rotating it affects everything at once - treat that as a more serious operation with a proper change window.
Suspending versus closing a subaccount
Subaccounts have a status field, and the two non-active values are very different in consequence.
Suspended is reversible. The subaccount stops processing but can be reactivated, and its resources remain. This is what you want for a customer who has stopped paying, an environment that is idle, or anything you might come back to.
Closed is permanent. Twilio’s documentation is explicit that a closed subaccount cannot be reopened. Phone numbers are released, and once released they go back to the pool and someone else can register them.
const twilio = require('twilio')
const client = twilio(
process.env.TWILIO_ACCOUNT_SID,
process.env.TWILIO_AUTH_TOKEN,
)
// Reversible
async function suspend(subaccountSid) {
const account = await client.api.v2010
.accounts(subaccountSid)
.update({ status: 'suspended' })
console.log(account.status)
}
// PERMANENT - cannot be undone
async function close(subaccountSid) {
const account = await client.api.v2010
.accounts(subaccountSid)
.update({ status: 'closed' })
console.log(account.status)
}
The two calls differ by one string. That is a genuinely uncomfortable API design for an operation this asymmetric, and it is worth guarding in your own code - require an explicit confirmation flag, log the intent before acting, and never let a closure run from a script that could be invoked with the wrong argument.
On the phone number point specifically: releasing a number you have published anywhere means losing it. Customers with it saved, printed materials, verification flows tied to it - all broken, with no way to get the number back.
Before you close anything
A checklist worth working through, because every item on it is irreversible after the fact.
- Move the phone numbers you want to keep. Numbers can be transferred to another account under the same parent before closure. Do this first - it is the item people most regret skipping.
- Export the data you need. Message and call logs, recordings, and transcriptions. Retention after closure is not something to rely on.
- Check for active subscriptions attached to the subaccount that will not clean themselves up.
- Confirm nothing is still sending traffic to it. Search your codebase and configuration for the subaccount SID.
- Confirm the final billing position so the closure does not leave an unexpected balance.
- Consider suspending first. Leave it suspended for a month. If nothing breaks and nobody asks, close it then.
// Transfer a number to another account before closing
await client
.incomingPhoneNumbers('PNxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
.update({ accountSid: process.env.TWILIO_TARGET_SUBACCOUNT_SID })
That suspend-first step is the highest-value item on the list. Suspension costs nothing and gives you a month of evidence that nothing depended on the subaccount, which is much better information than an audit of what you think depended on it.
Auditing what exists
Before revoking or closing, find out what you actually have. Most accounts of any age have accumulated more than anyone remembers.
export TWILIO_ACCOUNT_SID=ACxxxxxxxx
export TWILIO_AUTH_TOKEN=xxxxxxxx
# Subaccounts and their statuses
curl -s -u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
"https://api.twilio.com/2010-04-01/Accounts.json?PageSize=100" \
| jq -r '.accounts[] | "\(.sid)\t\(.status)\t\(.friendly_name)"'
# Numbers on a given subaccount
curl -s -u "$SUBACCOUNT_SID:$SUBACCOUNT_TOKEN" \
"https://api.twilio.com/2010-04-01/Accounts/$SUBACCOUNT_SID/IncomingPhoneNumbers.json" \
| jq -r '.incoming_phone_numbers[] | "\(.phone_number)\t\(.friendly_name)"'
Two things this typically surfaces. Subaccounts created for a trial or a customer that ended long ago and were never cleaned up - each potentially holding numbers that cost money monthly. And API keys nobody can account for, which are the ones worth investigating rather than simply deleting.
Before deleting a key whose purpose is unknown, check whether it is in use. Twilio’s usage and monitoring data can show recent activity by credential, and deleting an unidentified key that turns out to belong to a production integration is a self-inflicted outage.
Keeping credentials manageable
The reason revocation is stressful is usually that nobody knows where the credential lives. A few habits fix that permanently.
- One key per service, named after the service. A key called
billing-workercan be revoked with confidence. A key calledapi-key-2cannot. - Keys in the platform, not the repository. Environment variables injected at process start, so rotation is an edit and a restart rather than a rebuild and a redeploy.
- Never in an image. A credential baked into a container image persists in the layers and in any registry holding it.
- Subaccounts for isolation. Separate subaccounts for staging and production means a test script cannot send messages from your production number, and revoking one does not touch the other.
- Rotate on a schedule, not only after an incident. A rotation you have practised is a routine change; one you have never done is an outage waiting for a bad day.
On RunxBuild, a service takes environment variables in the dashboard, injected into the process at start. Rotating a Twilio key is updating the value and restarting - the credential is never in the repository or in an image, and the deploy log and runtime log sit together so a service failing on a bad credential says so on the first line.
How this fits the rest of the stack
Credential rotation is only painless when the credential lives in one place you can edit. Holding it in the platform rather than in a repository or an image turns a rotation into an edit and a restart, with the deploy log and runtime log in the same place when something does not come back up. The RunxBuild hosting calculator shows the service and its managed database as separate line items before you commit to the shape.
Useful related references:
- Deploy a Node.js API for Free on RunxBuild
- Deploy a .NET API for Free on RunxBuild
- Namecheap API for Developers: The Part the Docs Skip
- Services on RunxBuild
FAQ
How do I delete a Twilio API key?
In the console, open the account management area, find the page for auth tokens and API keys, select the key, and delete it. Revocation is immediate - create and deploy the replacement first, verify traffic is authenticating on it, and only then delete the old one.
What is the difference between suspending and closing a Twilio subaccount?
Suspending is reversible - the subaccount stops processing but can be reactivated with its resources intact. Closing is permanent and cannot be undone, and it releases the phone numbers back to the pool where someone else can register them.
Can I reopen a closed Twilio subaccount?
No. Twilio’s documentation is explicit that closure is permanent. If there is any chance you will want it back, suspend it instead and leave it suspended for a month before deciding - suspension costs nothing and gives you real evidence that nothing depended on it.
What happens to phone numbers when I close a subaccount?
They are released back to the pool and can be registered by someone else. Transfer any numbers you want to keep to another account under the same parent before closing, because there is no way to recover a released number afterwards.
How should I manage Twilio credentials to make rotation easy?
One key per service, named after that service, so it can be revoked with confidence. Hold the value in your deployment platform’s environment variables rather than in the repository or a container image, so rotation is an edit and a restart rather than a rebuild.