100) { http_response_code(400); throw new Exception("Key name must be 100 characters or less"); } // Validate expires_in_days if provided if ($expiresInDays !== null && $expiresInDays !== '') { $expiresInDays = (int)$expiresInDays; if ($expiresInDays < 1 || $expiresInDays > 3650) { http_response_code(400); throw new Exception("Expiration must be between 1 and 3650 days"); } } else { $expiresInDays = null; } // Use centralized database connection $conn = Database::getConnection(); // Generate API key $apiKeyModel = new ApiKeyModel($conn); $result = $apiKeyModel->createKey($keyName, $_SESSION['user']['user_id'], $expiresInDays); if (!$result['success']) { throw new Exception($result['error'] ?? "Failed to generate API key"); } // Log the action $auditLog = new AuditLogModel($conn); $auditLog->log( $_SESSION['user']['user_id'], 'create', 'api_key', $result['key_id'], ['key_name' => $keyName, 'expires_in_days' => $expiresInDays] ); // Clear output buffer ob_end_clean(); // Return success with the plaintext key (shown only once) header('Content-Type: application/json'); echo json_encode([ 'success' => true, 'api_key' => $result['api_key'], 'key_prefix' => $result['key_prefix'], 'key_id' => $result['key_id'], 'expires_at' => $result['expires_at'] ]); } catch (Exception $e) { ob_end_clean(); header('Content-Type: application/json'); // Preserve any specific status set before the throw (401/403/400/...); // only fall back to 500 when nothing more specific was set. $code = http_response_code(); if (!is_int($code) || $code < 400) { $code = 500; } http_response_code($code); if ($code >= 500) { error_log("Generate API key error: " . $e->getMessage()); echo json_encode([ 'success' => false, 'error' => 'An internal error occurred' ]); } else { echo json_encode([ 'success' => false, 'error' => $e->getMessage() ]); } }