Pro API Usage

Call the PYNE Flask Pro API as a consumer: health, /run, /run/batch, /optimize, chart preview, indicator preview, quick backtest, and auth.

This page

Pro API Usage

Abstract

The Pro API is the HTTP evaluate contract for PYNE: POST Pine source plus OHLCV, receive plots, series, events, drawings, and alerts. Free-tier evaluate endpoints (/run, /run/batch) are usable without a key. Bar/script/rate/concurrency and chart/mock-only data guards apply only when FREE_TIER_LIMITS is truthy (1 / true / yes / on); default off. Production compose sets ${FREE_TIER_LIMITS:-1}. Webhook URLs stay SSRF-safe regardless. Optional L2 alert webhooks POST last-bar firings to webhook_url or ALERT_WEBHOOK_URL. Pro preview/backtest routes track usage via API keys. This page is for callers (AXIS, scripts, workers). Server lifecycle and auth design are under API.

Conceptual model

Diagram

Rendering…

EndpointAuthPurpose
GET / / GET /healthnoneHealth + endpoint map (default_run_mode: auto)
POST /runnone (free)Single script evaluate
POST /run/batchnone (free)≤8 scripts, shared OHLCV
POST /optimizenone (free)Strategy hyperparameter search (docs)
POST /compile/prewarmnone (free)Warm Numba builtins / script IR
WS /ws/runnone (free)AXIS WebSocket evaluate channel
POST /preview/chartPro usageChart thumbnail
POST /preview/indicatorPro usageIndicator-style preview
POST /backtest/quickPro usageEquity / summary
POST /auth/create_keyadmin tokenMint key
GET /auth/usageProUsage stats
POST /auth/validatebody keyValidate key
POST /lsp/{completion,hover,diagnostics}none (free)AXIS HTTP LSP bridge — see LSP
/scripts · /cron/*PYNE_RUNNER=1Hosted scripts + bar-close (runner)

Default local bind: 127.0.0.1:5002.

Interface surface

Run the server (local)

pip install -r backend/requirements.txt
export API_KEY_STORE="$PWD/.data/api_keys.json"
python -m backend.app
# or: make run

Health

curl -s http://127.0.0.1:5002/ | python -m json.tool

POST /run

Schema (RUN_SCHEMA):

FieldTypeRequiredDefault
scriptstringyes
datalist (OHLCV bars)yes
symbolstringno"CHART"
data_sourcestringno""
data_optionsobjectno{}
modestringno"auto"
inputsobjectno{}input.* by title (forces interpret under auto)
librarieslistno[][{namespace, name, version, source}], max 32
timeout_secondsnumbernoomit — interpret wall-clock budget; passed only when set and > 0
profilerboolnofalse — forces interpret
webhook_urlstringno"" (else env ALERT_WEBHOOK_URL)
forward_alertsboolnotrue
alert_last_barboolnotrue
alert_batchboolnotrue

Unknown extra keys → UNKNOWN_FIELDS. Query ?mode= overrides only when the body omits mode.

Bar objects are expected to carry at least open/high/low/close/time (volume optional depending on script).

curl -s -X POST http://127.0.0.1:5002/run \
  -H 'Content-Type: application/json' \
  -d '{
    "script": "//@version=6\nindicator(\"Demo\")\nplot(ta.sma(close, 3))",
    "symbol": "AAPL",
    "mode": "interpret",
    "data": [
      {"time": 1, "open": 10, "high": 11, "low": 9, "close": 10.5, "volume": 1000},
      {"time": 2, "open": 10.5, "high": 12, "low": 10, "close": 11.5, "volume": 1100},
      {"time": 3, "open": 11.5, "high": 12.5, "low": 11, "close": 12, "volume": 1200}
    ]
  }'

Success shape (conceptual):

{
  "status": "success",
  "plots": [],
  "series": {},
  "plot_meta": {},
  "events": [],
  "drawings": [],
  "alerts": [],
  "script_id": "...",
  "run_id": "...",
  "count": 3,
  "mode": "interpret",
  "data_source": "chart"
}

When a webhook URL is configured, the response may also include alert_forward (delivery counts). See Alerts.

Error codes include NO_SCRIPT, NO_DATA, DATA_SOURCE_ERROR, EXECUTION_ERROR, plus schema codes INVALID_BODY, MISSING_FIELD, INVALID_FIELD, UNKNOWN_FIELDS.

POST /run/batch

Shared OHLCV, multiple scripts (max 8). Envelope:

{
  "scripts": [
    {"id": "sma", "script": "//@version=6\nindicator(\"s\")\nplot(ta.sma(close, 5))"},
    {"id": "rsi", "script": "//@version=6\nindicator(\"r\")\nplot(ta.rsi(close, 14))"}
  ],
  "data": [/* bars */],
  "symbol": "AAPL",
  "mode": "interpret",
  "libraries": []
}

String entries in scripts are accepted and auto-id’d as script_0, …. Per-script errors do not necessarily fail the whole HTTP status (route returns 200 with per-item status — verify against deployment).

POST /preview/chart (Pro)

{
  "script": "",
  "data": {"close": [100, 101, 102], "volume": [1, 2, 3]},
  "options": {
    "type": "line",
    "color": "#2196F3",
    "width": 600,
    "height": 300,
    "show_volume": false
  }
}

Response includes base64 PNG chart + meta. Width/height clamped (e.g. max 1200×600).

POST /preview/indicator (Pro)

{
  "expression": "ta.sma(close, 20)",
  "data": {"close": [/* ... */]},
  "options": {}
}

POST /backtest/quick (Pro)

{
  "script": "//@version=6\nstrategy(\"x\")\n...",
  "data": {},
  "initial_capital": 10000.0,
  "mock_data": true,
  "mock_bars": 252
}

POST /compile/prewarm (free)

Warm Numba builtins / optional script list so the first interactive /run with mode=auto|compile skips cold JIT. Soft-fails without Numba (object-mode compile still works).

curl -s -X POST http://127.0.0.1:5002/compile/prewarm \
  -H 'Content-Type: application/json' \
  -d '{"force": true}' | python -m json.tool

Optional body: scripts (list of Pine sources to compile-warm), force (re-run builtins). Response includes timing / prewarm stats. Deploy hosts may also set PYNE_COMPILE_PREWARM for once-per-worker start. See Compiler overview.

Auth helpers

# Mint key (admin)
curl -s -X POST http://127.0.0.1:5002/auth/create_key \
  -H "Content-Type: application/json" \
  -H "X-Admin-Token: $ADMIN_TOKEN" \
  -d '{"tier":"hobby"}'

# Validate
curl -s -X POST http://127.0.0.1:5002/auth/validate \
  -H "Content-Type: application/json" \
  -d '{"api_key":"pyn_..."}'

Send Pro requests with the key as required by middleware (Authorization: Bearer … / documented API-key header — see Auth and keys).

There is no pynescript.api.PynescriptAPI client in this package. Call the HTTP contract with requests / curl as above.

Internals (repo paths)

PathRole
backend/app.pyRoutes /, /run, /run/batch, /compile/prewarm, auth
backend/api/preview.py/preview/*, /backtest/quick
backend/middleware/schemas.pyStrict request schemas (mode default auto, alert flags)
backend/middleware/auth.pyKeys, usage, admin token
src/pynescript/runtime/host.pyPackage Runtime SoT (interpret / compile / auto)
backend/runtime.pyCompat shim → pynescript.runtime
backend/alert_forwarder.pyL2 webhook POST batching
backend/services/chart_renderer.pyPNG rendering
backend/services/backtest.pyQuick backtest + mock OHLCV

Invariants & edge cases

  • Max body 5 MiB — oversized JSON → Flask 413.
  • Strict schemas — unknown fields rejected.
  • CORS — browser clients need listed origins; server-to-server without Origin is fine.
  • mode default auto — prefer warm compile; fall back to interpret (auto_backend, optional compile_fallback_reason). Strict compile errors instead of falling back; use interpret for alerts, input.* overrides, libraries, and full request.*.
  • libraries (0.3.7+)[{namespace, name, version, source}] binds import ns/Name/ver (max 32). register_library_source finalizes exports in 0.3.8; auto-mode keeps the list on interpret fallback. Same field on Flask /run, /run/batch, pyne-worker /run, and deployed scripts.
  • timeout_seconds — optional interpret wall-clock budget on /run and /run/batch. Omit / null / ≤ 0 → no timeout. Exceeded runs surface timed_out on the HTTP body.
  • Alertsalerts[] on success (interpret). L2 webhooks: body webhook_url or env ALERT_WEBHOOK_URL; defaults last-bar + batch POST. See Alerts.
  • Batch cap 8TOO_MANY_SCRIPTS if exceeded.
  • Free-tier guards (0.3.4+; opt-in) — process-local limits on unauthenticated /run, /run/batch, /compile/prewarm (and WS run). Off unless FREE_TIER_LIMITS is 1 / true / yes / on. Production compose sets that to 1.
    EnvDefaultRole
    FREE_TIER_LIMITSoffMaster switch for the rows below
    FREE_MAX_BARS5000Max OHLCV bars (when on)
    FREE_MAX_SCRIPT_CHARS256 KiBMax Pine source length (when on)
    FREE_MAX_CONCURRENT4Simultaneous free runs per worker (when on)
    FREE_RATE_LIMIT / FREE_RATE_WINDOW_SEC60 / 60sSliding-window IP rate limit (when on)
    Free data_sourcechart / mock / none onlyNo outbound ccxt/yahoo on free paths (when on)
    Numeric knobs treat 0 as unlimited. Health features.free_tier_limits reports the master switch. Webhook URLs stay SSRF-filtered regardless. Put a reverse proxy in front for multi-worker production.
  • AXIS multi-indicator UIs prefer /run/batch to share bar payloads; read series + plot_meta (including fill band refs) for charts.

Worked examples

Python requests client for /run

import requests

SCRIPT = """
//@version=6
indicator("SMA", overlay=true)
plot(ta.sma(close, 5))
"""

bars = [
    {"time": i, "open": 100 + i, "high": 101 + i, "low": 99 + i, "close": 100.5 + i, "volume": 1000}
    for i in range(30)
]

r = requests.post(
    "http://127.0.0.1:5002/run",
    json={"script": SCRIPT, "data": bars, "symbol": "DEMO", "mode": "auto"},
    timeout=60,
)
r.raise_for_status()
payload = r.json()
assert payload["status"] == "success", payload
print(payload["count"], payload.get("mode"), list(payload.get("series", {})))
# optional: payload.get("alerts"), payload.get("alert_forward")

Batch two indicators

r = requests.post(
    "http://127.0.0.1:5002/run/batch",
    json={
        "scripts": [
            {"id": "sma", "script": "//@version=6\nindicator(\"s\")\nplot(ta.sma(close, 5))"},
            {"id": "ema", "script": "//@version=6\nindicator(\"e\")\nplot(ta.ema(close, 5))"},
        ],
        "data": bars,
    },
    timeout=120,
)
print(r.json())

Bind published libraries

r = requests.post(
    "http://127.0.0.1:5002/run",
    json={
        "script": '//@version=6\nimport Demo/Lib/1 as L\nindicator("t")\nplot(L.x)\n',
        "data": bars,
        "mode": "interpret",
        "libraries": [
            {
                "namespace": "Demo",
                "name": "Lib",
                "version": 1,
                "source": '//@version=6\nlibrary("Lib")\nexport x = 1.0\n',
            }
        ],
    },
    timeout=60,
)

Wire optional CCXT data source

{
  "script": "...",
  "data": [/* chart bars */],
  "symbol": "BTC/USDT",
  "data_source": "ccxt",
  "data_options": {"exchange": "binance"}
}

Requires server environment with ccxt installed.

Failure modes

Code / HTTPMeaningAction
400 MISSING_FIELDNo script/dataFix body
400 UNKNOWN_FIELDSExtra keysStrip undocumented fields
400 DATA_SOURCE_ERRORProvider configFix data_options / deps
500 EXECUTION_ERRORRuntime exceptionSimplify script; check message
403 on create_keyADMIN_TOKEN unset/wrongExport token
413Body too largeFewer bars / compress strategy
CORS browser errorOrigin not allowedUpdate ALLOWED_ORIGINS
Empty seriesScript never plottedAdd plot / check declaration

See also