API documentation
Last updated: November 3, 2026
Pro users (and admins) can call the same JSVMP obfuscation engines as the web workspace over HTTP. API calls share the monthly run quota with the web app.
1. Create an API key
Sign in, open Account, and create a key under API keys. Keys start with veil_live_ and are shown only once at creation. We store only a hash and cannot recover a key; if you lose it, revoke it and create a new one. Each account can keep up to 3 active keys. All keys stop working immediately if the plan drops to Free. The account page shows when each key was last used.
2. Request
POST https://vm.ldvmp.com/api/v1/obfuscate
- Header
Authorization: Bearer <your key> - Header
Content-Type: application/json - Body
{ "code": "<JavaScript source>", "mode": "performance" | "dynamic" }:performanceis the high-performance VM,dynamicthe dynamic VM - API requests accept up to 2 MB of source code each.
3. Response
On success the API returns 200:
{
"ok": true,
"output": "/* obfuscated JavaScript */ ...",
"inputBytes": 22,
"outputBytes": 48213,
"ms": 184,
"engine": "performance",
"engineVersion": "…"
}The X-Quota-Limit and X-Quota-Remaining headers report this month’s limit and remaining runs.
4. Errors
Every error returns { "ok": false, "error": "<code>", "message": "<details>" }. Quota example:
{ "ok": false, "error": "QUOTA_EXCEEDED", "message": "Monthly run limit reached for this plan.",
"limit": 1000, "used": 1000, "remaining": 0, "resetAt": "2026-12-01T00:00:00.000Z" }
| HTTP | error | Meaning |
|---|---|---|
| 401 | INVALID_KEY | Missing, malformed, revoked, or unknown key |
| 403 | PLAN_REQUIRED | The key owner is no longer Pro (keys stop working immediately after a downgrade) |
| 400 | BAD_REQUEST | Invalid JSON, empty code, or mode is not performance / dynamic |
| 413 | PAYLOAD_TOO_LARGE | Source code exceeds 2 MB per request |
| 415 | UNSUPPORTED_MEDIA_TYPE | Content-Type is not application/json |
| 422 | COMPILE_FAILED | The source could not be compiled (the run is not charged) |
| 429 | QUOTA_EXCEEDED | Monthly runs used up; the response includes limit / remaining / resetAt |
| 503 | ENGINE_UNAVAILABLE / TIMEOUT | The engine is warming up or timed out |
| 503 | QUOTA_UNAVAILABLE / UNAVAILABLE | The quota or key service is temporarily unavailable |
Every 503 is retryable and none is charged: wait for the Retry-After header (seconds, also in the JSON field retryAfter), then retry | ||
| 500 | INTERNAL_ERROR | Unexpected server error (the run is not charged); retry later |
5. curl example
curl -X POST https://vm.ldvmp.com/api/v1/obfuscate \
-H "Authorization: Bearer $VEILVM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"code":"console.log(\"hello\")","mode":"performance"}'
6. Node.js example
// Node.js 18+ (built-in fetch). Store the key in an environment variable, never in source.
import { readFile, writeFile } from "node:fs/promises";
const code = await readFile("input.js", "utf8");
const response = await fetch("https://vm.ldvmp.com/api/v1/obfuscate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VEILVM_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ code, mode: "dynamic" })
});
const data = await response.json();
if (!data.ok) throw new Error(`${response.status} ${data.error}: ${data.message}`);
await writeFile("output.js", data.output);
console.log(`${data.engine}: ${data.inputBytes} → ${data.outputBytes} bytes in ${data.ms} ms`);
7. Security tips
- Never embed a key in browser code or commit it to a repository; keep it in a server-side environment variable.
- Revoke a key from the account page as soon as you suspect it leaked.
- Standard requests are processed in memory and your code is never written to logs. Large files are stored temporarily in private storage and deleted automatically within 24 hours.