Quick Start
Get your first ZPL result in under 60 seconds. Choose your language below and copy-paste the example to get started.
import requests # Your API key (get one at zero-point-logic.io) API_KEY = "zpl_your_api_key_here" BASE_URL = "https://web-production-5ece2.up.railway.app" def compute_zpl(bias, N=7, samples=10000): """Compute ZPL p_output for given parameters.""" headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"} payload = { "bias": bias, "N": N, "samples": samples } response = requests.post( f"{BASE_URL}/samples", json=payload, headers=headers ) response.raise_for_status() return response.json() # Test with biased input — ZPL always returns ~0.5 result = compute_zpl(bias=0.9, N=7, samples=50000) print(f"Input bias: 0.9 → p_output: {result['p_output']:.4f}") # Output: Input bias: 0.9 → p_output: 0.5001
const API_KEY = "zpl_your_api_key_here"; const BASE_URL = "https://web-production-5ece2.up.railway.app"; async function computeZPL(bias, N = 7, samples = 10000) { const response = await fetch(`${BASE_URL}/samples`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": API_KEY }, body: JSON.stringify({ bias, N, samples }) }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return response.json(); } // Test: biased input always returns ~0.5 computeZPL(0.75, 9, 20000) .then(result => console.log(`p_output: ${result.p_output}`)) .catch(err => console.error(err));
# Basic request — compute p_output curl -X POST "https://web-production-5ece2.up.railway.app/samples" \ -H "Content-Type: application/json" \ -H "X-API-Key: zpl_your_api_key_here" \ -d '{ "bias": 0.85, "N": 7, "samples": 10000 }' # Response: # { # "p_output": 0.5002, # "bias": 0.85, # "N": 7, # "samples": 10000, # "elapsed_ms": 42 # } # Health check (no auth required) curl "https://web-production-5ece2.up.railway.app/health"
API Reference
All endpoints are served over HTTPS. The API accepts and returns JSON.
Compute the ZPL output probability (p_output) for a given input bias, matrix size N, and number of Monte Carlo samples. This is the primary endpoint for all ZPL computations.
{
"bias": 0.85,
"N": 7,
"samples": 10000
}
{
"p_output": 0.5003,
"bias": 0.85,
"N": 7,
"samples": 10000,
"elapsed_ms": 38,
"version": "1.0"
}
| PARAMETER | TYPE | REQUIRED | RANGE | DESCRIPTION |
|---|---|---|---|---|
| bias | float | Required | 0.0 – 1.0 | Input probability of a 1-bit. 0.5 = fair, 0.9 = highly biased. |
| N | integer | Required | 3 – 25 | Matrix dimension. Odd values recommended (3, 5, 7, 9…). |
| samples | integer | Optional | 100 – 50,000 | Number of Monte Carlo samples. Default: 10,000. Higher = more precise. |
Run a full bias sweep from 0.0 to 1.0 in configurable steps for a fixed N. Returns an array of (bias, p_output) pairs showing ZPL's equilibrium property across all bias values.
GET /sweep?N=7&steps=20&samples=5000
{
"N": 7,
"steps": 20,
"results": [
{"bias":0.0, "p_output":0.4998},
{"bias":0.05, "p_output":0.5001},
// ... 18 more rows
{"bias":1.0, "p_output":0.4997}
]
}
Health check endpoint. No authentication required. Returns API status, uptime, and version information. Use this to verify connectivity before making computation requests.
{
"status": "ok",
"version": "1.0",
"uptime_seconds": 86400,
"engine": "ZPL-Core",
"timestamp": "2026-03-29T12:00:00Z"
}
Alias for /samples. Accepts identical request body and returns identical response structure. Provided for semantic clarity — use whichever endpoint name matches your mental model.
Authentication
All computation endpoints require a valid API key passed in the request header. Keys are tied to your subscription plan and enforce rate limits.
X-API-Key Header
POST /samples HTTP/1.1 Host: web-production-5ece2.up.railway.app X-API-Key: zpl_live_abc123xyz456def789 Content-Type: application/json
| PLAN | REQUESTS/MONTH | MAX SAMPLES | MAX N | SWEEP ACCESS |
|---|---|---|---|---|
| FREE | 1,000 | 10,000 | 15 | No |
| BASIC | 10,000 | 25,000 | 21 | Yes |
| PRO | 50,000 | 50,000 | 25 | Yes |
| ENTERPRISE | Unlimited | 50,000 | 25 | Yes |
Error Codes
The API uses standard HTTP status codes. Error responses always include a JSON body with a message field.
{
"error": "Bad Request",
"message": "Parameter 'bias' must be between 0.0 and 1.0",
"status": 400,
"request_id": "req_abc123"
}
Rate Limits
Rate limits are enforced per API key on a rolling monthly window. Exceeding limits returns a 429 with a Retry-After header.
| PLAN | MONTHLY REQUESTS | BURST (per min) | CONCURRENT | PRICE |
|---|---|---|---|---|
| FREE | 1,000 | 10 | 1 | $0 |
| BASIC | 10,000 | 60 | 3 | $9/mo |
| PRO | 50,000 | 200 | 10 | $29/mo |
| ENTERPRISE | Unlimited | 1,000 | 50 | Custom |
Language Examples
Drop-in classes for the most common use cases. Copy, paste, configure your API key.
import requests from dataclasses import dataclass from typing import List, Dict @dataclass class ZPLResult: p_output: float bias: float N: int samples: int elapsed_ms: int class ZPLClient: """Official ZPL Python client.""" BASE_URL = "https://web-production-5ece2.up.railway.app" def __init__(self, api_key: str): self.session = requests.Session() self.session.headers.update({ "X-API-Key": api_key, "Content-Type": "application/json" }) def compute(self, bias: float, N: int = 7, samples: int = 10000) -> ZPLResult: r = self.session.post(f"{self.BASE_URL}/samples", json={"bias": bias, "N": N, "samples": samples}) r.raise_for_status() data = r.json() return ZPLResult(**{k: data[k] for k in ZPLResult.__dataclass_fields__}) def sweep(self, N: int = 7, steps: int = 20) -> List[Dict]: r = self.session.get(f"{self.BASE_URL}/sweep", params={"N": N, "steps": steps}) r.raise_for_status() return r.json()["results"] def health(self) -> Dict: return self.session.get(f"{self.BASE_URL}/health").json() # Usage zpl = ZPLClient("zpl_your_key") res = zpl.compute(bias=0.9, N=9, samples=50000) print(f"p_output = {res.p_output:.4f}") # ≈ 0.5000
class ZPLClient { constructor(apiKey) { this.apiKey = apiKey; this.baseUrl = "https://web-production-5ece2.up.railway.app"; } async compute(bias, N = 7, samples = 10000) { const res = await fetch(`${this.baseUrl}/samples`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": this.apiKey }, body: JSON.stringify({ bias, N, samples }) }); if (!res.ok) throw new Error(`ZPL Error ${res.status}`); return res.json(); } async sweep(N = 7, steps = 20) { const res = await fetch(`${this.baseUrl}/sweep?N=${N}&steps=${steps}`, { headers: { "X-API-Key": this.apiKey } }); return res.json(); } async health() { return (await fetch(`${this.baseUrl}/health`)).json(); } } // Usage const zpl = new ZPLClient("zpl_your_key"); zpl.compute(0.8, 7, 10000).then(r => console.log(`p_output: ${r.p_output}`));
using System.Collections; using UnityEngine; using UnityEngine.Networking; public class ZPLClient : MonoBehaviour { private const string API_KEY = "zpl_your_key"; private const string BASE_URL = "https://web-production-5ece2.up.railway.app"; [System.Serializable] public class ZPLRequest { public float bias; public int N; public int samples; } [System.Serializable] public class ZPLResponse { public float p_output; public float bias; public int N; public int elapsed_ms; } public IEnumerator ComputeZPL(float bias, int N, System.Action<ZPLResponse> callback) { var req = new ZPLRequest { bias = bias, N = N, samples = 10000 }; string json = JsonUtility.ToJson(req); using var www = new UnityWebRequest(BASE_URL + "/samples", "POST"); www.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(json)); www.downloadHandler = new DownloadHandlerBuffer(); www.SetRequestHeader("Content-Type", "application/json"); www.SetRequestHeader("X-API-Key", API_KEY); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { var resp = JsonUtility.FromJson<ZPLResponse>(www.downloadHandler.text); callback?.Invoke(resp); } } }