Endpoint
Revokes an API key, making it immediately invalid for all future API requests. This is a permanent action that cannot be undone.
Path Parameters
The unique identifier of the API key to revoke
Query Parameters
The owner identifier. This must match the owner of the API key being revoked for authorization
Response
Returns HTTP 204 No Content on success.
Example Request
curl -X DELETE "https://api.blnk.io/api-keys/api_key_abc123def456?owner=user_123abc" \
-H "Authorization: Bearer YOUR_API_KEY"
Success Response
HTTP 204 No Content (empty body)
Error Responses
Error message describing what went wrong
Common Errors
- 401 Unauthorized: Missing or invalid owner parameter
- 403 Forbidden: The owner doesn’t match the API key owner (unauthorized)
- 404 Not Found: API key not found
- 500 Internal Server Error: Failed to revoke API key
Important Considerations
Once an API key is revoked:
- It becomes invalid immediately
- All requests using this key will fail with 401 Unauthorized
- The change cannot be undone
- The key cannot be reactivated
Active Requests
Requests that are in-flight when the key is revoked:
- May complete successfully if already authenticated
- New requests will fail immediately
Use Cases
Security Incident Response
Revoke compromised keys immediately:
const handleSecurityIncident = async (compromisedKeyId, owner) => {
console.log('Security incident detected!');
console.log(`Revoking API key: ${compromisedKeyId}`);
const response = await fetch(
`https://api.blnk.io/api-keys/${compromisedKeyId}?owner=${owner}`,
{
method: 'DELETE',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
if (response.status === 204) {
console.log('✓ Key revoked successfully');
// Create a new key to replace it
const newKey = await createApiKey({
name: `Replacement for ${compromisedKeyId}`,
owner,
scopes: ['transactions:read', 'balances:read'],
expires_at: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString()
});
console.log('✓ New key created');
return newKey;
}
};
Key Rotation
Revoke old keys during rotation:
const rotateApiKey = async (oldKeyId, owner, config) => {
// Step 1: Create new key
console.log('Creating new API key...');
const newKey = await fetch('https://api.blnk.io/api-keys', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: `${config.name} (Rotated ${new Date().toISOString().split('T')[0]})`,
owner: config.owner,
scopes: config.scopes,
expires_at: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString()
})
}).then(r => r.json());
console.log('✓ New key created:', newKey.api_key_id);
// Step 2: Update your application configuration
console.log('Updating application configuration...');
await updateAppConfig(newKey.key);
// Step 3: Wait for propagation (optional)
console.log('Waiting for configuration to propagate...');
await new Promise(resolve => setTimeout(resolve, 5000));
// Step 4: Revoke old key
console.log('Revoking old API key...');
await fetch(`https://api.blnk.io/api-keys/${oldKeyId}?owner=${owner}`, {
method: 'DELETE',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
console.log('✓ Old key revoked');
console.log('✓ Rotation complete!');
return newKey;
};
Cleanup Expired Keys
Revoke keys that have already expired:
const cleanupExpiredKeys = async (owner) => {
// Get all keys
const keys = await fetch(`https://api.blnk.io/api-keys?owner=${owner}`, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());
const now = new Date();
// Find expired but not revoked keys
const expiredKeys = keys.filter(key =>
!key.is_revoked && new Date(key.expires_at) <= now
);
console.log(`Found ${expiredKeys.length} expired keys to revoke`);
// Revoke each expired key
for (const key of expiredKeys) {
await fetch(`https://api.blnk.io/api-keys/${key.api_key_id}?owner=${owner}`, {
method: 'DELETE',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
console.log(`✓ Revoked expired key: ${key.name}`);
}
return expiredKeys.length;
};
Employee Offboarding
Revoke all keys for a departing employee:
const offboardEmployee = async (employeeId) => {
console.log(`Offboarding employee: ${employeeId}`);
// Get all keys for this employee
const keys = await fetch(`https://api.blnk.io/api-keys?owner=${employeeId}`, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());
// Filter active keys
const activeKeys = keys.filter(key => !key.is_revoked);
console.log(`Found ${activeKeys.length} active keys`);
// Revoke all active keys
const results = await Promise.all(
activeKeys.map(key =>
fetch(`https://api.blnk.io/api-keys/${key.api_key_id}?owner=${employeeId}`, {
method: 'DELETE',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
})
)
);
const successCount = results.filter(r => r.status === 204).length;
console.log(`✓ Revoked ${successCount} of ${activeKeys.length} keys`);
return {
employee_id: employeeId,
keys_revoked: successCount,
total_keys: keys.length
};
};
Revoke with Confirmation
Implement safe revocation with confirmation:
const safeRevokeKey = async (keyId, owner) => {
// Get key details
const keys = await fetch(`https://api.blnk.io/api-keys?owner=${owner}`, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());
const key = keys.find(k => k.api_key_id === keyId);
if (!key) {
throw new Error('Key not found');
}
if (key.is_revoked) {
console.log('Key is already revoked');
return;
}
// Show details
console.log('\nKey to revoke:');
console.log(` Name: ${key.name}`);
console.log(` Scopes: ${key.scopes.join(', ')}`);
console.log(` Created: ${key.created_at}`);
console.log(` Last used: ${key.last_used_at}`);
console.log(` Expires: ${key.expires_at}`);
// In a real application, get user confirmation
const confirmed = true; // Replace with actual confirmation
if (confirmed) {
const response = await fetch(
`https://api.blnk.io/api-keys/${keyId}?owner=${owner}`,
{
method: 'DELETE',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
if (response.status === 204) {
console.log('\n✓ Key revoked successfully');
} else {
console.error('\n✗ Failed to revoke key');
}
} else {
console.log('\n✗ Revocation cancelled');
}
};
Best Practices
1. Verify Before Revoking
Always verify the key details before revoking:
// Good: Check key details first
const key = await getApiKeyDetails(keyId, owner);
if (key.name.includes('production')) {
console.warn('Warning: This is a production key!');
}
await revokeKey(keyId, owner);
// Bad: Revoke without checking
await revokeKey(keyId, owner);
2. Have a Replacement Ready
For production keys, create a replacement before revoking:
// Good: Create new key first
const newKey = await createApiKey(config);
await updateAppConfig(newKey.key);
await revokeKey(oldKeyId, owner);
// Bad: Revoke without replacement
await revokeKey(keyId, owner);
// Service is now down!
3. Log Revocations
Maintain an audit trail:
const revokeKeyWithLogging = async (keyId, owner, reason) => {
const key = await getApiKeyDetails(keyId, owner);
// Log before revoking
await auditLog({
action: 'api_key_revoked',
key_id: keyId,
key_name: key.name,
owner,
reason,
timestamp: new Date().toISOString()
});
await revokeKey(keyId, owner);
};
4. Notify Stakeholders
Inform relevant parties when revoking keys:
const revokeKeyWithNotification = async (keyId, owner) => {
const key = await getApiKeyDetails(keyId, owner);
// Revoke the key
await revokeKey(keyId, owner);
// Notify
await sendNotification({
to: owner,
subject: 'API Key Revoked',
message: `API key "${key.name}" has been revoked.`
});
};
When to Revoke
Revoke API keys when:
- Security incident: Key has been compromised or exposed
- Key rotation: Part of regular security maintenance
- Employee departure: Access should be removed
- Project termination: Integration is being shut down
- Expiration: Key has expired and is no longer needed
- Over-privileged: Key has more permissions than needed (create a new one with correct scopes)
- Unused: Key hasn’t been used in a long time
Recovery
If you accidentally revoke a key:
- You cannot unrevoke - Revocation is permanent
- Create a new key with the same configuration
- Update applications to use the new key
- Document the incident for audit purposes