Skip to content
Loading live market data…

Developers

API reference

REST over HTTPS, JSON only. Read the signal feed, provider directory and aggregate performance; approved providers can publish and close attributed signals. A public sandbox key means you can make a real request before creating an account.

Quickstart

This works right now — the sandbox key below is public and requires no account.

curl

curl -H "Authorization: Bearer tofan_sandbox_demo" \
  "https://vhzdqlzyvuemieieenys.supabase.co/functions/v1/public-api/signals?status=active"

Python

pip install requests

from tofan import TofanClient

client = TofanClient()              # defaults to the sandbox key
for s in client.signals(status="closed"):
    print(s.pair, s.direction, s.result, s.pips_result)

Market data straight into pandas

import io, pandas as pd
from tofan import TofanClient

client = TofanClient(api_key="tofan_...")
df = pd.read_csv(io.StringIO(client.candles_csv("EURUSD", "1d")))
df["candle_time"] = pd.to_datetime(df["candle_time"])
print(df[["candle_time", "close", "rsi_14", "ema_50"]].tail())

JavaScript

const res = await fetch("https://vhzdqlzyvuemieieenys.supabase.co/functions/v1/public-api/signals?status=active", {
  headers: { Authorization: "Bearer tofan_sandbox_demo" },
});
const { signals } = await res.json();

Try it

Live requests against the production API using the sandbox key. Nothing here is mocked — if these stop working, this page is wrong.

Authentication

Every request needs a bearer token. Issue keys from Dashboard → Security → Developer. Only a SHA-256 hash of your key is stored, so a database leak yields no usable credentials — which also means a lost key cannot be recovered, only replaced.

Header

Authorization: Bearer tofan_your_key_here

read scope

The three GET endpoints. Available on any account.

publish scope

POST endpoints. Issued only to approved signal providers, because what a publish key writes carries that provider's attribution.

Sandbox

tofan_sandbox_demo is a public read-only key returning three fixed sample signals and two sample providers. Query parameters are genuinely applied to the fixtures, so what you build against the sandbox behaves the same live.

Publish calls with the sandbox key are validated exactly like real ones and echoed back with sandbox: true, but write nothing.

Rate limits

60 requests per minute per key by default. Exceeding it returns 429 with a Retry-After header and retry_after_seconds in the body. The Python SDK retries automatically.

Endpoints

Errors

StatusMeaningWhat to do
401Key missing, malformed, revoked or unknown.Check the Authorization header format: Bearer tofan_…
403Key is valid but lacks the scope this call needs.Publish scope is issued only to approved providers.
404No matching resource, or it is not yours.Closing a signal only works on your own active signals.
429Rate limit exceeded.Wait for Retry-After seconds. The SDK does this for you.
500Unexpected server error.Retry once; if it persists, check /status.

Python SDK

Typed models, automatic 429 retry, and typed exceptions so you can tell a bad key from an exhausted quota without parsing strings. Only dependency is requests.

Download tofan.pySingle file, no build step — drop it beside your code.

Errors are typed

from tofan import TofanClient, PermissionError_, RateLimitError

client = TofanClient(api_key="tofan_...")

try:
    client.publish_signal("EURUSD", "BUY", 1.0842, stop_loss=1.0798)
except PermissionError_:
    print("this key is read-only")
except RateLimitError as e:
    print(f"slow down; retry in {e.retry_after}s")

Component health for these endpoints is on the status page; feed coverage is on the infrastructure page.