API Reference
The Hardcaml Web IDE backend exposes a simple REST API.
Base URL
Section titled “Base URL”- Production:
https://hardcaml.tg3.dev - Development:
http://localhost:8000
Endpoints
Section titled “Endpoints”POST /compile
Section titled “POST /compile”Compile and run Hardcaml code.
Request
Section titled “Request”{ "files": { "circuit.ml": "open! Core\nopen! Hardcaml\n...", "circuit.mli": "open! Hardcaml\n...", "test.ml": "open! Core\n..." }, "timeout_seconds": 60}| Field | Type | Required | Description |
|---|---|---|---|
files | object | Yes | Map of filename → content |
timeout_seconds | number | No | Max execution time (default: 60) |
Required Files
Section titled “Required Files”circuit.mlor custom name - Implementationcircuit.mlior custom name - Interfacetest.ml- Test harness
Response (Success)
Section titled “Response (Success)”{ "success": true, "output": "Test output...", "waveform": "┌Signals────────┐┌Waves...", "waveform_vcd": "$timescale 1ns $end...", "compile_time_ms": 1234, "run_time_ms": 567, "tests_passed": 3, "tests_failed": 0}Response (Compile Error)
Section titled “Response (Compile Error)”{ "success": false, "stage": "compile", "error_type": "compile_error", "error_message": "File \"circuit.ml\", line 10..."}Response (Rate Limited)
Section titled “Response (Rate Limited)”{ "success": false, "error_type": "rate_limit", "error_message": "Too many builds. Please wait..."}HTTP Status: 429
GET /health
Section titled “GET /health”Health check endpoint.
Response
Section titled “Response”{ "status": "healthy"}Rate Limiting
Section titled “Rate Limiting”- Default: 10 requests/minute per IP
- Configurable:
RATE_LIMIT_PER_MINUTEenv var - Response: HTTP 429 when exceeded
The API allows cross-origin requests from any origin.
Using from JavaScript
Section titled “Using from JavaScript”async function compileCode(circuit, interface_, test) { const response = await fetch('https://hardcaml.tg3.dev/compile', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ files: { 'circuit.ml': circuit, 'circuit.mli': interface_, 'test.ml': test } }) });
if (response.status === 429) { throw new Error('Rate limited'); }
return response.json();}Using the Shared UI Components
Section titled “Using the Shared UI Components”If you’re building a React application, use the @hardcaml/ui package:
import { OcamlEditor, OutputPanel, useCompiler } from '@hardcaml/ui';
function MyPlayground() { const [code, setCode] = useState('...'); const compiler = useCompiler({ apiBase: 'https://hardcaml.tg3.dev' });
return ( <> <OcamlEditor value={code} onChange={setCode} /> <button onClick={() => compiler.compile({ ... })}>Run</button> <OutputPanel result={compiler.result} /> </> );}