TLDR: Check this fixed working example of the code you provided. This one uses your current approach, so it executes the script tag manually.
The answer is that there's no pretty way of doing what you want, as briefly stated in specs 4.3.1, 8.4 and 8.2.3.5 of the HTML Standard, when parsing <script>, the scripts won't be executed, so you'll have to either do it manually, or renderize your script as a source page:
Changing the src, type, charset, async, and defer attributes dynamically has no direct effect; these attribute are only used at specific times described below.
The scripting flag is set to "enabled" if scripting was enabled for the Document with which the parser is associated when the parser was created, and "disabled" otherwise.
The scripting flag can be enabled even when the parser was originally created for the HTML fragment parsing algorithm, even though script elements don't execute in that case.
For your current approach, as it is to call the API's as a service, and then adding the HTML and expecting the JS to be executed. Unfortunately, there's no pretty way of doing this. Similar questions had been asked several times in SO (answer1, answer2, answer3, answer4, etc.). Most of them end up doing something like this:
// (1) to load js files
var scripts = document.getElementsByTagName('script');
Array.from(scripts).forEach(function(node) {
var parent=node.parentElement
var script = document.createElement('script');
script.src = node.src;
parent.insertBefore(script, node);
parent.removeChild(node);
});
// (2) to execute directly js
var scripts = document.getElementsByTagName('script');
Array.from(scripts).forEach(function(script) {
eval(script.innerHTML);
});
As caveant, this solution may end up in other issues (like unsafe-eval, and more).
2. Load your API inside an IFRAME
Best way would be as suggested in comments, to load your whole api response as an individual HTML page inside an IFRAME. Something similar to this:
<iframe id="pdf1"></iframe>
<script>
document.getElementById('pdf1').src = '../path/to/api/which/returns/the/html-with-js-here?parameter1=value1¶meter2=value2&etc=values';
</script>
I personally recommend this approach as it is the more natural way. Also, you have something all those other question/answer don't have; you have an API dedicated to retrieve your HTML with JS. So just, instead of calling in it as an API, navigate to it.
let scriptDiv = document.createElement('div'); scriptDiv.innerHTML = myHtml ; const scripts = scriptDiv.querySelectorAll('script'); for (let i = 0; i < scripts.length; i++) { document.body.appendChild(scripts[i]); }