API documentation

Run untrusted Python, JavaScript, Java and C++ code from your product with one REST API. Send source code and stdin; get stdout, stderr, compiler output and exit codes from an isolated sandbox with no network access.

Private beta. Limits and runtime versions below are current and may change; changes are announced in advance. API version 1.0.0-beta.

Overview

Executions are asynchronous: POST /v1/executions returns 202 immediately with an executionId; poll GET /v1/executions/{executionId} until the status is terminal.

Base URL: https://api.tatvastack.com

Quickstart

  1. Sign in to the dashboard and create an API key under API keys. It is shown once; store it on your server.
  2. Submit code, then poll for the result:
export CODEFORGE_API_KEY=cf_live_...   # from the dashboard

curl -s -X POST https://api.tatvastack.com/v1/executions \
  -H "Authorization: Bearer $CODEFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"language":"python","source":"print(input()[::-1])","stdin":"hello"}'
# {"executionId":"exe_…","status":"QUEUED","createdAt":"…","statusUrl":"/v1/executions/exe_…"}

curl -s https://api.tatvastack.com/v1/executions/exe_… \
  -H "Authorization: Bearer $CODEFORGE_API_KEY"
# {"executionId":"exe_…","status":"SUCCEEDED","stdout":"olleh\n","exitCode":0, …}
import os, time, uuid, requests

API = "https://api.tatvastack.com"
HEADERS = {"Authorization": f"Bearer {os.environ['CODEFORGE_API_KEY']}"}

def run(language, source, stdin=""):
    r = requests.post(f"{API}/v1/executions", json={"language": language, "source": source, "stdin": stdin},
                      headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())}, timeout=10)
    r.raise_for_status()
    execution_id = r.json()["executionId"]
    while True:
        result = requests.get(f"{API}/v1/executions/{execution_id}", headers=HEADERS, timeout=10).json()
        if result["status"] not in ("QUEUED", "RUNNING"):
            return result
        time.sleep(0.75)

result = run("python", "print(sum(range(10)))")
print(result["status"], result["stdout"])   # SUCCEEDED 45
// Node.js 18+ (built-in fetch)
const API = 'https://api.tatvastack.com';
const headers = { Authorization: `Bearer ${process.env.CODEFORGE_API_KEY}`, 'Content-Type': 'application/json' };

async function run(language, source, stdin = '') {
  const res = await fetch(`${API}/v1/executions`, {
    method: 'POST',
    headers: { ...headers, 'Idempotency-Key': crypto.randomUUID() },
    body: JSON.stringify({ language, source, stdin }),
  });
  if (!res.ok) throw new Error((await res.json()).error.message);
  const { executionId } = await res.json();
  for (;;) {
    const result = await (await fetch(`${API}/v1/executions/${executionId}`, { headers })).json();
    if (!['QUEUED', 'RUNNING'].includes(result.status)) return result;
    await new Promise((r) => setTimeout(r, 750));
  }
}

const result = await run('javascript', 'console.log(6 * 7)');
console.log(result.status, result.stdout); // SUCCEEDED 42

Authentication

Send your key as a bearer token: Authorization: Bearer cf_live_…. Keys belong to your account; revoking one in the dashboard rejects it on the next request. Never put an API key in browser or mobile code: call CodeForge from your backend.

Languages & runtimes

languageRuntimeExample
pythonCPython 3.12
name = input()
print(f"Hello, {name}!")
javascriptNode.js 24
const name = require('fs').readFileSync(0, 'utf8').trim();
console.log(`Hello, ${name}!`);
javaOpenJDK 21
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, " + new Scanner(System.in).nextLine() + "!");
    }
}
cppg++ 11 · C++17
#include <iostream>
#include <string>
int main() {
    std::string name;
    std::getline(std::cin, name);
    std::cout << "Hello, " << name << "!" << std::endl;
}

Standard library only: no package installation and no network access. Java: put main in any class; the file is named after your public class automatically. Java and C++ are compiled first; compiler errors return COMPILE_ERROR with compileOutput.

Execution lifecycle

QUEUED/RUNNING are in progress; the rest are terminal.

Poll every 500–1000 ms; polling does not use quota. Measured median time from request to result for a short program on a warm sandbox, from a client in India to us-east-1: Python 966 ms, JavaScript 900 ms, Java 1.3 s, C++ 846 ms (Java and C++ include compilation). The first run after an idle period starts a fresh sandbox and can take a few seconds longer.

Retries & idempotency

Send an Idempotency-Key header (a UUID per logical request) with every POST, and retry with the same key: you get the original execution back (header Idempotent-Replayed: true), with no second run and no extra charge. Reusing a key with a different body returns 409 IDEMPOTENCY_CONFLICT. Keys are remembered for 24 hours.

Limits & quotas

Source code / stdin64 KiB each
Run time (limits.timeMs)default 5,000 ms, max 10,000 ms; compilation has its own budget
Output64 KiB per stream (stdout, stderr, compileOutput); truncated: true when cut
Memoryfixed per language: about 512 MiB for Python and C++ programs, 256 MiB heap for JavaScript and Java
Free plan500 runs per calendar month (UTC), 1 execution in flight at a time

Every accepted POST counts as one run, except executions that end in PLATFORM_ERROR, which are refunded. Rejected requests (4xx) are never charged. Check usage with GET /v1/usage or in the dashboard. Responses include X-Quota-Limit and X-Quota-Remaining.

Errors

Every error has the same shape. Include requestId (also in the X-Request-Id header) when contacting support at bhaskar@tatvastack.com.

{
  "error": {
    "code": "CONCURRENCY_LIMIT",
    "message": "Your free plan allows 1 execution at a time. …",
    "requestId": "req_…",
    "retryable": true
  }
}
CodeHTTPMeaning
VALIDATION_ERROR400The body is invalid (missing field, unknown language, too long). Fix the request.
INVALID_IDEMPOTENCY_KEY400Idempotency-Key must be 1–255 characters of A–Z a–z 0–9 . _ : -
BAD_REQUEST400The request could not be processed (for example malformed JSON).
UNAUTHORIZED401Missing, invalid or revoked API key.
NOT_FOUND404No such execution in your account, or no such route.
IDEMPOTENCY_CONFLICT409This Idempotency-Key was already used with a different request.
PAYLOAD_TOO_LARGE413Request body too large.
QUOTA_EXCEEDED429Monthly allowance used up. Not retryable until resetsAt.
CONCURRENCY_LIMIT429Too many executions in flight for your plan. Retry after one finishes.
INTERNAL_ERROR500Unexpected error on our side. Safe to retry with the same Idempotency-Key.

Data retention

Source code and stdinDeleted as soon as the execution finishes (or fails). Never written to logs.
Results (stdout, stderr, compiler output, status)Kept for 24 hours after submission, then deleted. GET returns 404 afterwards.
Usage countsKept for billing: runs per day by language and status, without code or output.
Queued jobsEncrypted at rest; held for at most a day, or 4 days if processing failed repeatedly.

Sandbox & security

Each language runs in its own isolated micro-VM-based sandbox with no network route out (no internet, no DNS), no cloud credentials, process and memory limits, a wall-clock kill, and capped output. Jobs are encrypted for the sandbox and results are signed, and leftover files and processes are removed between runs. During the beta, CodeForge is invite-only while an independent security review is completed; we make no certification claims.

API reference

POST/v1/executions

Submit code for execution.

Queues one execution. Counts as one run against your monthly allowance and occupies one concurrency slot until it finishes.

Send an Idempotency-Key to make retries safe: the same key with the same request returns the original execution without a new run or charge.

Parameters

  • Idempotency-Key (header): Unique key for this logical request (recommended: a UUID). Valid for 24 hours. Reusing it with a different request body returns 409.

Request body

FieldTypeDetails
languagerequiredstringpython, javascript, java, cpp
python (CPython 3.12), javascript (Node.js 24), java (OpenJDK 21), cpp (g++ 11, C++17, -O2).
sourcerequiredstringmax 65,536 chars
Program source (UTF-8, up to 64 KiB). Java: the class with main may have any name; a public class must match its name automatically.
stdinstringmax 65,536 chars · default ""
Standard input (up to 64 KiB).
limitsobject
timeMs: integer 100–10000, default 5000. Wall-clock limit for running the program. Compilation (Java/C++) has a separate budget and is not counted.

Responses

202Accepted and queued (or an idempotent replay of an earlier request).
400Invalid body (VALIDATION_ERROR) or Idempotency-Key (INVALID_IDEMPOTENCY_KEY).
401Missing, invalid or revoked API key.
409The Idempotency-Key was already used with a different request.
413Request body too large.
429CONCURRENCY_LIMIT (retryable: wait for a running job to finish) or QUOTA_EXCEEDED (not retryable until resetsAt).
500Unexpected server error. Safe to retry with the same Idempotency-Key.

GET/v1/executions/{executionId}

Get an execution's status and result.

Poll until status is terminal (anything other than QUEUED or RUNNING). Polling does not use quota. A sensible interval is 500–1000 ms. Results are kept for 24 hours after submission and then deleted; after that this returns 404. Source code and stdin are deleted as soon as the execution finishes.

Parameters

  • executionId (path, required):

Responses

200The execution.
401Missing, invalid or revoked API key.
404No such execution in your account.
500Unexpected server error. Safe to retry with the same Idempotency-Key.

GET/v1/usage

Get quota and usage.

This month's allowance and usage, current concurrency, and a daily breakdown for the last 30 days (UTC).

Responses

200Usage summary.
401Missing, invalid or revoked API key.
500Unexpected server error. Safe to retry with the same Idempotency-Key.

Machine-readable spec: OpenAPI 3.1 (JSON). Import it into Postman, Insomnia or a client generator.