Skip to main content

Overview

Generates a new API key for the user. The old key is immediately invalidated.
This action cannot be undone! The old API key will stop working immediately.

Authentication

Requires User API Key in the X-API-Key header (the old key you’re replacing).

Request

POST https://api.syncline.run/v1/user/api-key/regenerate
No request body required.

Response

{
  "success": true,
  "api_key": "sk_user_new_abc123xyz789...",
  "message": "API key regenerated successfully"
}
success
boolean
Always true on successful regeneration
api_key
string
Your new API key. Save this immediately - it will never be shown again.

When to Regenerate

Security Breach

If your API key is exposed:
const response = await fetch('https://api.syncline.run/v1/user/api-key/regenerate', {
  method: 'POST',
  headers: {
    'X-API-Key': oldUserApiKey
  }
});

const { api_key } = await response.json();

// Save new key immediately
localStorage.setItem('syncline_user_api_key', api_key);

Regular Rotation

Rotate keys periodically as a security best practice:
// Remind users to rotate keys every 90 days
if (daysSinceLastRotation > 90) {
  showNotification({
    title: 'Security Reminder',
    message: 'It's time to rotate your API key',
    action: 'Rotate Now',
    onClick: async () => {
      const { api_key } = await regenerateUserKey();
      localStorage.setItem('syncline_user_api_key', api_key);
      showSuccess('API key rotated successfully!');
    }
  });
}

User Flow

Settings Page

// In user settings page
function SecuritySettings() {
  const [showConfirm, setShowConfirm] = useState(false);

  const handleRegenerate = async () => {
    if (!confirm('This will invalidate your old API key. Continue?')) {
      return;
    }

    try {
      const { api_key } = await fetch(
        'https://api.syncline.run/v1/user/api-key/regenerate',
        {
          method: 'POST',
          headers: { 'X-API-Key': currentApiKey }
        }
      ).then(r => r.json());

      // Save new key
      localStorage.setItem('syncline_user_api_key', api_key);

      // Show success message with new key
      alert(`New API Key: ${api_key}\n\nSave this key - it won't be shown again!`);

      // Reload page with new key
      window.location.reload();
    } catch (error) {
      alert('Failed to regenerate API key: ' + error.message);
    }
  };

  return (
    <div>
      <h3>API Key</h3>
      <p>Current key: {currentApiKey.substring(0, 20)}...</p>
      <button onClick={handleRegenerate}>
        Regenerate API Key
      </button>
      <p className="warning">
        ⚠️ This will immediately invalidate your old key
      </p>
    </div>
  );
}

Automated Rotation

// Automatically rotate after suspicious activity
async function handleSuspiciousActivity(userId) {
  console.warn(`Suspicious activity detected for user ${userId}`);

  // Automatically regenerate key
  const { api_key } = await regenerateUserKey();

  // Email user about security action
  await sendEmail({
    to: user.email,
    subject: 'Security Alert: API Key Regenerated',
    body: `
      We detected suspicious activity on your account and automatically
      regenerated your API key as a security measure.

      Your new API key is: ${api_key}

      If this wasn't you, please contact support immediately.
    `
  });

  // Log security event
  await auditLog.create({
    event: 'api_key_auto_regenerated',
    user_id: userId,
    reason: 'suspicious_activity',
    timestamp: new Date()
  });
}

Best Practices

Show Key Only Once

function RegenerateKeyButton() {
  const [newKey, setNewKey] = useState(null);

  const handleClick = async () => {
    const { api_key } = await regenerateKey();
    setNewKey(api_key);
  };

  if (newKey) {
    return (
      <div className="key-display">
        <h3>Your New API Key</h3>
        <code>{newKey}</code>
        <button onClick={() => navigator.clipboard.writeText(newKey)}>
          Copy to Clipboard
        </button>
        <p>⚠️ Save this key now - it won't be shown again!</p>
      </div>
    );
  }

  return (
    <button onClick={handleClick}>
      Regenerate API Key
    </button>
  );
}

Require Confirmation

async function regenerateWithConfirmation() {
  // Show modal
  const confirmed = await showModal({
    title: 'Regenerate API Key?',
    message: 'Your old API key will immediately stop working. Continue?',
    confirmText: 'Yes, Regenerate',
    cancelText: 'Cancel'
  });

  if (!confirmed) return;

  // Proceed with regeneration
  const { api_key } = await regenerateKey();

  return api_key;
}

Audit Trail

async function regenerateWithAudit(userId) {
  const { api_key } = await regenerateKey();

  // Log the rotation
  await db.securityEvents.create({
    user_id: userId,
    event: 'api_key_regenerated',
    timestamp: new Date(),
    ip_address: req.ip,
    user_agent: req.headers['user-agent']
  });

  return api_key;
}

Security Considerations

Immediate Invalidation

The old key stops working immediately:
const oldKey = 'sk_user_old_abc123...';

// Regenerate
const { api_key: newKey } = await regenerateKey();

// Old key is now INVALID
try {
  await fetch('https://api.syncline.run/v1/user/info', {
    headers: { 'X-API-Key': oldKey }
  });
} catch (error) {
  console.log('Old key no longer works ✓');
}

Never Share Keys

// Bad: Sharing key with others
const sharedKey = 'sk_user_abc123...';
sendToColleague(sharedKey); // ❌ Never do this!

// Good: Each user has their own key
const myKey = localStorage.getItem('syncline_user_api_key'); // ✓

Error Responses

Invalid API Key

{
  "error": "Unauthorized",
  "message": "Invalid or missing API key"
}

Rate Limit

{
  "error": "Too many regeneration attempts",
  "message": "Please wait before regenerating again"
}