Skip to Content
API ReferenceOverview

API Reference

Base URL

https://juhus.ee/api/v1

All requests route through the apps/web proxy. There is no separate subdomain for the API.

Money and prices

All EUR amounts are in integer cents. 500 = €5.00, 12345 = €123.45. There are no decimal fields.

  • Prices are integers 1–99 and represent the implied probability percentage of the YES outcome (e.g. price 62 = 62% probability).
  • Volumes (yesVolume, noVolume) are in EUR-cents, representing the total value of contracts traded on each side.
  • Balances are in EUR-cents.

Each fill charges a taker fee in EUR-cents. See Fees.

Authentication

Public read-only endpoints require no credentials. Authenticated endpoints require a Bearer token:

Authorization: Bearer jk_...

API keys are created at Account → API Keys in the web app. See Authentication for details.

The minted JWT used by the browser is an internal mechanism: it is not exposed through this API. External integrations always use jk_* API keys.

Rate limits

BucketApplies toLimit
v1All public endpoints60 req / 60 s per IP
v1-authAuthenticated REST (per IP)120 req / 60 s per IP
v1-userAuthenticated REST (per user/API key)120 req / 60 s per user
sse:marketGET /markets/:id/stream120 connections / 60 s per IP
sse:userGET /user/stream30 / 60 s per user (120 / 60 s per IP)

When a limit is exceeded the server responds with 429 Too Many Requests and a Retry-After header (seconds).

Error format

All error responses share this shape:

{ "error": "Human-readable message", "code": "MACHINE_READABLE_CODE" }

The code field is present only on errors that callers should handle programmatically (e.g. INSUFFICIENT_BALANCE, INSUFFICIENT_LIQUIDITY). Generic errors omit it.

Common status codes

CodeMeaning
200Success
201Created (new order placed)
400Bad request: invalid parameters
401Unauthorized: missing or invalid token
404Not found
405Method not allowed
429Rate limit exceeded
500Internal server error
503Transient conflict, safe to retry

Pagination

Endpoints that return lists accept page (default 1) and limit (default 20, max 50) query parameters and return a meta object:

{ "data": [...], "meta": { "total": 143, "page": 1, "limit": 20, "hasMore": true } }

SSE conventions

Server-Sent Events streams use Content-Type: text/event-stream. Each frame is:

data: <JSON payload>\n\n

Keep-alive frames are sent every 25 seconds:

: ping\n\n

Disconnect and reconnect on any network error. The market stream sends a full snapshot on reconnect; the user stream sends a { "type": "connected" } frame.

Sell-order inversion

Sell orders are stored internally with the side inverted (a YES sell is stored as a NO buy at price 100 - P) but the API always returns orders in the user-facing representation: side and price match what you submitted. See Orders for details.