# EVIO API — Developer Documentation

> Complete developer reference for the EVIO API. MCP-native financial-data primitives for AI agents. Eight Year-1 endpoints behind real auth and metering. Reasoned, decision-shaped outputs with citations and confidence scores.

**EVIO, Inc.** is a Colorado corporation (HQ Henderson, NV), publicly traded on the **OTC Current** tier of OTC Markets (ticker `OTC: EVIO`). The Company files annual and quarterly disclosures and audited financials through OTC Markets' Alternative Reporting Standard. **EVIO is not an SEC-registered issuer.**

- HTML version: https://evioinc.com/api/docs/
- OpenAPI 3.1: https://api.evioinc.com/openapi.json
- Schemas (open source, MIT): https://github.com/JpDeSilva17/evio-schemas
- llms-full.txt: https://evioinc.com/llms-full.txt
- API base: https://api.evioinc.com/v1
- MCP server: https://api.evioinc.com/mcp

---

## Quick start

```bash
curl -H "Authorization: Bearer evk_test_..." \
  "https://api.evioinc.com/v1/options/unusual?ticker=XNAS:AAPL&lookback=30d&limit=5"
```

You'll get back JSON with `results`, `_reasoning`, `_citations`, `_confidence`, `_links`, and `_meta`. See response envelope below.

Get an API key at https://app.evioinc.com/sign-up?invite=alpha. Test keys (`evk_test_*`) bypass billing while still logging usage.

---

## Authentication

Bearer API keys exclusively. OAuth is for the dashboard only — never on the API surface.

```
Authorization: Bearer evk_test_xxxxxxxxxxxxxxxxxxxxxxxx
```

| Prefix       | Environment | Counts toward bill | Logs usage |
|--------------|-------------|--------------------|------------|
| `evk_test_*` | Test        | No                 | Yes        |
| `evk_live_*` | Live        | Yes                | Yes        |

Keys are SHA-256 hashed at rest; plaintext is shown once at creation. Per-agent keys are recommended (each agent gets its own monthly cap, budget cap, audit trail, and 1-second pause/revoke kill switch).

---

## Response envelope

Every successful (2xx) response includes:

```json
{
  "results": [ /* endpoint-specific payload */ ],
  "_reasoning":   ["sentence 1.", "sentence 2."],
  "_citations":   [{ "step": 0, "source": "...", "locator": "..." }],
  "_confidence":  { "score": 0.87, "label": "high", "factors": ["..."] },
  "_links":       [{ "id": "XNAS:AAPL", "endpoints": ["..."] }],
  "_meta": {
    "request_id": "req_01HXY...",
    "latency_ms": 142,
    "data_freshness": "mock",
    "tokens_estimated": 318,
    "version": "v1"
  }
}
```

| Field          | Purpose                                                                                           |
|----------------|---------------------------------------------------------------------------------------------------|
| `_reasoning`   | Ordered, atomic, one-sentence reasoning steps. Pass directly to your LLM — no re-derivation.       |
| `_citations`   | Each citation links a `_reasoning` step to its data source.                                        |
| `_confidence`  | Numeric `score` (0..1) + categorical `label` + `factors[]` that raised or lowered it.              |
| `_links`       | Canonical IDs surfaced + EVIO endpoints that accept them. Composability hint for agent planners.   |
| `_meta`        | `request_id`, `latency_ms`, `data_freshness` (mock/shadow/live), `tokens_estimated`, `version`.    |

### Opt-in fields via `?include=`

- `_alternatives` — results that ranked just below
- `_counterfactual` — what the result would be if a single key input changed
- `_suggestions` — 0–3 follow-up tool calls

### `data_freshness`

- `mock` — returning deterministic mock data (default during closed alpha)
- `shadow` — real provider was called and logged for diff; mock data still returned to client
- `live` — returning real provider output

The mock → shadow → live transition is a single env-var flip on the server. Customer code never changes.

---

## Error envelope

```json
{
  "error": {
    "code": "invalid_ticker_format",
    "message": "Field 'ticker' must be in MIC:SYMBOL format. Received 'apple'. Try 'XNAS:AAPL'.",
    "recoverable": true,
    "retry_after_ms": null,
    "docs_url": "https://evioinc.com/api/docs/#errors",
    "request_id": "req_01HXY...",
    "hints": [
      { "field": "ticker", "action": "transform", "suggestion": "XNAS:AAPL" }
    ]
  }
}
```

`recoverable: true` → agent fixes input and retries. `recoverable: false` → escalate to human. `hints[]` is structured remediation; agents don't have to parse prose.

### Catalog

| Code                          | HTTP | Recoverable | Description                                                                       |
|-------------------------------|------|-------------|-----------------------------------------------------------------------------------|
| `missing_authorization`       | 401  | yes         | Missing Bearer token. Set `Authorization` header.                                |
| `invalid_api_key_format`      | 401  | yes         | Token must start with `evk_test_` or `evk_live_`.                                |
| `invalid_api_key`             | 401  | no          | Key not recognized; may have been revoked or never existed.                      |
| `invalid_ticker_format`       | 400  | yes         | `ticker` must be MIC:SYMBOL (e.g. `XNAS:AAPL`).                                  |
| `invalid_request_body`        | 400  | yes         | Body failed schema validation. See `hints` for which field.                      |
| `invalid_accession_number`    | 400  | yes         | `accession_number` must match `##########-##-######`.                            |
| `agent_budget_exceeded`       | 429  | no          | Agent hit monthly cap. Resets next month.                                        |
| `rate_limit_exceeded`         | 429  | yes         | Per-key limit exceeded. See `retry_after_ms`.                                    |
| `data_freshness_stale`        | 503  | yes         | Provider returned stale data; will be re-fetched. Retry recommended.             |
| `data_provider_unavailable`   | 503  | no          | `EVIO_DATA_MODE=live` but provider not implemented.                              |
| `job_not_found`               | 404  | no          | Job ID does not exist or belongs to a different org.                             |
| `internal_error`              | 500  | no          | Unexpected server error. Contact support@evioinc.com with `request_id`.          |

Error codes never change meaning. New codes are added; old codes are not repurposed.

---

## Conventions

| Item               | Convention                                                      |
|--------------------|-----------------------------------------------------------------|
| Tickers            | ISO 10383 MIC + symbol, e.g. `XNAS:AAPL`, `XNYS:JPM`            |
| SEC filings        | Accession number, format `##########-##-######`                 |
| Dates              | ISO 8601 strings; never separate year/month/day                 |
| Currencies         | USD as numbers (no string formatting, no commas)                |
| Booleans           | `true` / `false` only                                           |
| Null vs. omit      | Omit null/missing fields. Don't expect both forms.              |
| Request IDs        | `req_<base32>` — opaque; surfaced in `X-Request-Id` header      |
| Idempotency        | POST endpoints accept `Idempotency-Key: <UUIDv4>` header        |

---

## Pagination & rate limits

Cursor-based pagination: `?cursor=opaque_string&limit=50` (max 200). Next cursor in `_meta.next_cursor`.

Rate limits per key:

| Tier       | req/min |
|------------|---------|
| Indie      | 60      |
| Studio     | 600     |
| Pro        | 6,000   |
| Enterprise | Custom  |

Headers:

```
X-RateLimit-Limit:     60
X-RateLimit-Remaining: 58
X-RateLimit-Reset:     45    # seconds until full refill
X-Request-Id:          req_01HXY...
```

429 carries `retry_after_ms` so agents back off correctly.

---

## Field selection

| Setting           | Behavior                                                                  |
|-------------------|---------------------------------------------------------------------------|
| (default)         | Slim shape — minimum surface for typical agent decisions.                  |
| `?fields=a,b,c`   | Comma-separated allow-list.                                                |
| `?fields=*`       | Full payload (alias for `?verbose=true`).                                  |
| `?verbose=true`   | Same as `?fields=*`.                                                      |

`?include=` is separate — it adds the opt-in envelope fields `_alternatives`, `_counterfactual`, `_suggestions`.

---

## Endpoints

### `evio_options_unusual` — `GET /v1/options/unusual`

Top N tickers with statistically unusual options activity over a lookback window. Each result includes contract details, a volume z-score vs. baseline, an open-interest delta indicating new vs. closing positioning, and a reasoning trace.

**Parameters:**
- `ticker` (string, required) — MIC:SYMBOL or comma-separated batch up to 50
- `lookback` (string, default `30d`) — one of `7d`, `14d`, `30d`, `60d`, `90d`
- `limit` (integer, default 5) — 1..50

**When to use:** unusual options flow, gamma squeeze candidates, accumulation signals.
**When NOT to use:** backtesting strategies (use `evio_backtest_run`); portfolio Greeks (use `evio_portfolio_risk`).

```bash
curl -H "Authorization: Bearer $EVIO_KEY" \
  "https://api.evioinc.com/v1/options/unusual?ticker=XNAS:AAPL&lookback=30d&limit=5"
```

### `evio_factor_score` — `POST /v1/factor/score`

Multi-factor decomposition (value / momentum / quality / low-vol / size) plus composite score for a basket of up to 50 tickers.

**Body:**
```json
{
  "tickers": ["XNAS:AAPL", "XNAS:MSFT"],
  "factors": ["value", "momentum", "quality", "low_vol", "size"],
  "as_of":   "2026-05-01"
}
```

**When NOT to use:** single-name research (use `evio_equity_research`); risk decomposition (use `evio_portfolio_risk`).

### `evio_backtest_run` / `evio_backtest_run_async` — `POST /v1/backtest/run`

Submit a strategy spec; receive equity curve, Sharpe, max drawdown, exposure stats. Three execution modes: sync (default, 60s timeout), streaming (`Accept: text/event-stream`), and async (`mode: "async"` returns a `job_id`; poll `/v1/jobs/{id}` or subscribe to `job.completed` webhook).

**Body (minimum):**
```json
{
  "name":     "60-40 monthly rebalance",
  "universe": ["XNAS:AAPL", "..."],
  "rules":    {},
  "start":    "2020-01-01",
  "end":      "2025-12-31",
  "mode":     "sync"
}
```

### `evio_equity_research` — `GET /v1/equity/research`

Composite equity research package for a single ticker — rating, target price, top drivers (positive + negative), comparable set, upcoming catalysts.

```bash
curl -H "Authorization: Bearer $EVIO_KEY" \
  "https://api.evioinc.com/v1/equity/research?ticker=XNAS:AAPL&horizon=12m"
```

### `evio_regime_classify` — `GET /v1/regime/classify`

Macro regime (risk-on / risk-off / late-cycle / early-cycle) with confidence and configurable history. Subscribable via `regime.changed` webhook.

```bash
curl -H "Authorization: Bearer $EVIO_KEY" \
  "https://api.evioinc.com/v1/regime/classify?region=us&history=30"
```

### `evio_news_sentiment` — `GET /v1/news/sentiment`

Aggregated news tone for a single ticker over a window, with 90-day rolling baseline and z-score; returns top contributing headlines.

```bash
curl -H "Authorization: Bearer $EVIO_KEY" \
  "https://api.evioinc.com/v1/news/sentiment?ticker=XNAS:AAPL&window=7d"
```

### `evio_sec_filing` — `GET /v1/sec/filing`

Pulls an SEC filing by accession number, returns a structured section summary, and (by default) diffs against the prior filing of the same form type.

```bash
curl -H "Authorization: Bearer $EVIO_KEY" \
  "https://api.evioinc.com/v1/sec/filing?accession_number=0000320193-25-000001&diff=true"
```

### `evio_portfolio_risk` — `POST /v1/portfolio/risk`

Submit a portfolio. Returns 1-day and 10-day VaR, expected shortfall, factor exposures, named-scenario impacts, top concentration risks.

```bash
curl -X POST -H "Authorization: Bearer $EVIO_KEY" -H "Content-Type: application/json" \
  -d '{"positions":[{"ticker":"XNAS:AAPL","weight":0.3,"qty":100}],"horizon_days":10,"confidence":0.95}' \
  https://api.evioinc.com/v1/portfolio/risk
```

---

## MCP server

`https://api.evioinc.com/mcp` across all three current MCP transports: `stdio`, `http+sse`, `streamable-http`. Discovery via `https://api.evioinc.com/.well-known/mcp`.

### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "evio": {
      "url": "https://api.evioinc.com/mcp",
      "transport": "streamable-http",
      "headers": { "Authorization": "Bearer evk_test_REPLACE_ME" }
    }
  }
}
```

### Cursor

`~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "evio": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-fetch", "https://api.evioinc.com/mcp"],
      "env": { "AUTHORIZATION": "Bearer evk_test_REPLACE_ME" }
    }
  }
}
```

### LangChain (Python)

```python
import os
os.environ["EVIO_API_KEY"] = "evk_test_..."

from langchain_tools import EVIO_TOOLS  # from github.com/JpDeSilva17/evio-schemas
from langchain.agents import create_react_agent
from langchain_anthropic import ChatAnthropic

agent = create_react_agent(ChatAnthropic(model="claude-sonnet-4-6"), tools=EVIO_TOOLS)
```

### CrewAI (Python)

```python
import os
os.environ["EVIO_API_KEY"] = "evk_test_..."

from crewai_tools import EVIO_TOOLS
from crewai import Agent, Crew, Task

analyst = Agent(role="Quant analyst", goal="...", tools=EVIO_TOOLS)
crew = Crew(agents=[analyst], tasks=[Task(description="...")])
crew.kickoff()
```

### Anthropic SDK (tool use)

```python
import anthropic, json
client = anthropic.Anthropic()
tools = json.loads(open("anthropic-tools.json").read())  # from github.com/JpDeSilva17/evio-schemas

resp = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "What's the macro regime?"}],
)
```

### OpenAI Agents SDK / function calling

```python
from openai import OpenAI
import json
client = OpenAI()
tools = json.loads(open("openai-functions.json").read())

resp = client.chat.completions.create(
    model="gpt-5",
    messages=[{"role": "user", "content": "Find unusual options on AAPL."}],
    tools=tools,
)
```

### Vercel AI SDK / Mastra / Voltagent (TypeScript)

```ts
import { tool } from "ai";
import { z } from "zod";

export const evioOptionsUnusual = tool({
  description: "Top N tickers with unusual options activity over a lookback.",
  parameters: z.object({
    ticker:   z.string(),
    lookback: z.enum(["7d","14d","30d","60d","90d"]).default("30d"),
    limit:    z.number().int().min(1).max(50).default(5),
  }),
  execute: async ({ ticker, lookback, limit }) => {
    const r = await fetch(
      `https://api.evioinc.com/v1/options/unusual?ticker=${ticker}&lookback=${lookback}&limit=${limit}`,
      { headers: { Authorization: `Bearer ${process.env.EVIO_API_KEY}` } },
    );
    return r.json();
  },
});
```

---

## Webhooks

### Events

- `regime.changed` — macro regime classification flipped
- `agent.budget_warning` — agent crossed 80% of monthly cap
- `agent.budget_exceeded` — agent hit 100%
- `job.completed` — async job finished
- `job.failed` — async job failed terminally
- `alert.fired` (v1.1) — user-configured threshold crossed

### Delivery

- HMAC-SHA256 signature in `X-Evio-Signature` header. Verify before processing.
- Exponential backoff up to 24 hours, then dead-lettered.
- Idempotent — every event has a UUID; customers should dedupe.
- Replay from `app.evioinc.com/settings/webhooks`, last 100 events kept.

### Verifying signatures

```python
import hmac, hashlib
def verify(secret: str, body: bytes, signature: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
```

```ts
import crypto from "node:crypto";
export function verify(secret: string, body: string, sig: string): boolean {
  const expected = crypto.createHmac("sha256", secret).update(body).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}
```

---

## Discovery surfaces

Both human and machine. Both must work.

| URL                                                      | Returns                                                       |
|----------------------------------------------------------|---------------------------------------------------------------|
| `https://evioinc.com/llms.txt`                           | llmstxt.org-compliant overview optimized for LLM ingest        |
| `https://evioinc.com/llms-full.txt`                      | Full reference in one fetchable file                           |
| `https://api.evioinc.com/.well-known/mcp`                | MCP server URL, transports, auth, capabilities                 |
| `https://api.evioinc.com/.well-known/openapi`            | Pointer to current OpenAPI document                            |
| `https://api.evioinc.com/.well-known/agent-capabilities` | Compact JSON tool/schema/example manifest                      |
| `https://api.evioinc.com/openapi.json`                   | OpenAPI 3.1                                                    |
| `https://evioinc.com/.well-known/security.txt`           | Standard security contact (RFC 9116)                           |

---

## Public schemas repo

`evio-schemas` is the **public, MIT-licensed** companion repo:

→ **https://github.com/JpDeSilva17/evio-schemas**

Contains: `v1.yaml` (OpenAPI 3.1), framework wrappers (`anthropic-tools.json`, `openai-functions.json`, `langchain_tools.py`, `crewai_tools.py`), MCP manifest, copy-paste configs for Claude Desktop and Cursor, SemVer-tagged with min 90-day deprecation timelines.

Every breaking change ships with at least 90 days of deprecation notice via the `Deprecation` and `Sunset` HTTP headers on the live API and a `## Deprecated` section in the schemas `CHANGELOG.md`.

---

## Status & support

- Status page: https://status.evioinc.com
- Changelog: https://evioinc.com/api/changelog.html
- Security: https://evioinc.com/api/security.html
- Pricing: https://evioinc.com/api/pricing.html
- Terms / Privacy / AUP: https://evioinc.com/api/legal/
- Email: info@evioinc.com

---

## Closed alpha

The eight endpoints currently return mock JSON in their final response shape. Live market-data integration is targeted Q3 2026 as a transparent provider swap — field names, types, and the envelope are stable, so customer code does not change.

---

*This page contains forward-looking statements within the meaning of Section 27A of the Securities Act of 1933 and Section 21E of the Securities Exchange Act of 1934. Statements about future capabilities, GA timelines, customer counts, revenue, certifications, or partnerships are not guarantees of future performance.*
