Skip to main content
← ReferenceIntroduction

Get started with the EX7 Capital API

The EX7 Capital API is a REST surface over our trading infrastructure. You manage strategies, listen for live signals via Server-Sent Events, configure alerts, and validate strategies with The Judge, all from the same bearer-authenticated origin.

Base URL

https://api.ex7capital.com

The local dev server (when running uvicorn src.api.main:app inside the trading-agent repo) listens on http://127.0.0.1:8100. CORS is configured per-environment via ALLOWED_ORIGINS.

Authentication

Every authenticated endpoint expects a Supabase-issued JWT in the Authorizationheader.

Authorization: Bearer eyJhbGciOiJI...

Obtain the token client-side via the Supabase JS SDK (supabase.auth.getSession()) or server-side via your backend. We never reissue tokens, Supabase owns the auth surface. A token without the necessary tier returns 403 Forbidden; a missing or expired token returns 401 Unauthorized.

Public endpoints (e.g., /api/health, /api/billing/tiers, the unsubscribe webhook) are explicitly marked as such in the reference. Send no header for those, sending a token is harmless but unnecessary.

Rate limits + quotas

Per-tier limits apply to the bearer subject. Burst limits are enforced per minute; daily quotas reset at 00:00 UTC. The per-signal-per-day quota gates how many alert deliveries we will dispatch on the user’s behalf.

TierRequests/minRequests/dayAlerts/day
Free3050020
Operator12010,000200
Strategist600100,0002,000

Hitting a limit returns 429 Too Many Requests. The Retry-After header is always set, read it, sleep, retry. Don’t hammer the API; we will throttle harder.

Error codes

StatusNameMeaning
401UnauthorizedMissing or invalid bearer token. Re-authenticate via Supabase.
403ForbiddenToken is valid but the user lacks the tier required (e.g., Strategist-only endpoint hit by an Operator).
404Not FoundResource does not exist or is not owned by the authenticated user.
409ConflictOptimistic-concurrency clash. The `If-Match` etag did not match the current row.
412Precondition FailedCompliance gate: user has not yet accepted ToS / Risk / Privacy. Hit /api/billing/compliance/accept first.
422Unprocessable EntityRequest body shape is fine but failed semantic validation (e.g., strategy graph cycle).
429Too Many RequestsRate limit or daily quota exceeded. Read the `Retry-After` header.
500Internal Server ErrorSomething on our side broke. We get paged automatically; please retry with exponential backoff.
503Service UnavailableAn upstream dependency (Supabase, Rithmic, Stripe) is degraded. Safe to retry.

Error responses always carry a JSON body of the form {"detail": "..."} for FastAPI’s default handler. For 422 we include the failed-validation locator path so clients can map the error to a specific field.

Versioning

The API is currently v1, surfaced under /api/.... We do not version paths today (no /v1/ prefix); breaking changes will land behind a new path prefix or require a tier opt-in flag. Schema-additive changes are non-breaking.

SDKs

We do not yet ship official SDKs. The reference page generates copy-pasteable cURL, Python (httpx), and JavaScript (fetch) samples for every endpoint. OpenAPI tooling such as openapi-generator will produce a typed client from /openapi.json if you need one.

Webhooks

We accept inbound webhooks from Stripe (billing lifecycle) and Resend (email delivery events) on /api/billing/webhook and /api/alerts/webhooks/email. Both verify signatures before doing anything else; tampered payloads return 400.

Outbound webhooks (us → your service) are a v1.1 feature, not yet shipped. Track the changelog for the launch.

One quick request

Probe liveness without any auth:

curl -X GET 'https://api.ex7capital.com/api/health'

A live API returns 200 with a JSON body that includes status, postgresql, and last_signal_time.

When you’re ready, jump into the full reference.