# Asha API documentation Asha's evidence-grounded medical intelligence over the A2A v1.0 protocol. Base URL https://api.askasha.org. Human-readable pages: https://askasha.org/developers/docs. ## Overview The Asha API returns Asha's evidence-grounded medical answers over the open A2A v1.0 protocol (HTTP and JSON). Every answer ships with its sources. Keys created on askasha.org reach Asha only. ### At a glance | Item | Value | | --- | --- | | Base URL | `https://api.askasha.org` | | Protocol | A2A v1.0 over HTTPS, JSON bodies. Every response carries the `A2A-Version: 1.0` header. | | Authentication | `Authorization: Bearer ` on every call except signup and health. | | Agent | `asha` (alias `health`). Omitting `agent_id` defaults to Asha. | | Key scope | Asha only. Any other agent id returns 403. | | Input | `text/plain` inside JSON message parts, up to 500,000 characters per message. | | Output | A task with a `response` artifact (Markdown text) and a `provenance` artifact (sources, citations, evidence count, model). | | Free plan | 50 queries a month, 10 a day, no card. Paid plans in Plans, limits, and errors. | ### Endpoints | Method | Path | Purpose | Auth | | --- | --- | --- | --- | | POST | `/a2a/v1/message:send` | Ask Asha; returns the completed task. | API key | | POST | `/a2a/v1/message:stream` | Same request, streamed as server-sent events. | API key | | GET | `/a2a/v1/tasks/{task_id}` | Fetch one task. | API key | | GET | `/a2a/v1/tasks` | List your tasks (paginated, filterable). | API key | | POST | `/a2a/v1/tasks/{task_id}:cancel` | Cancel a task that is still working. | API key | | GET | `/a2a/v1/health` | Service health. | None | | POST | `/api/a2a/signup` | Create a free key. | None | | GET | `/api/a2a/usage` | Usage and limits for your key. | API key | | GET, PUT | `/api/a2a/preferences` | Saved defaults for your key: name, tone, audience, length, emoji (Customize your agent). | API key | | POST | `/api/a2a/rotate-key` | Replace your key; the old one stops at once. | API key | | POST | `/api/a2a/upgrade` | Stripe checkout for a paid plan. | API key | | GET | `/api/a2a/portal` | Stripe billing portal. | API key | | POST | `/v1/chat/completions` | OpenAI Chat Completions wire format over Asha (Drop-in with OpenAI SDKs). | API key | | GET | `/v1/models` | Model ids for the OpenAI-compatible endpoint. | API key | | GET | `/api/a2a/baa` | Current Business Associate Agreement (JSON, Markdown, HTML). | None | | POST | `/api/a2a/baa/accept` | Accept the agreement for your account (BAA, self-serve). | API key | | GET | `/api/a2a/baa/status` | Acceptance state and PHI readiness. | API key | ### First call ```bash curl -X POST https://api.askasha.org/a2a/v1/message:send \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "asha", "message": { "role": "user", "parts": [{"text": "Which antihypertensives are safe in pregnancy?"}] }, "metadata": {"audience": "clinician", "session_id": "visit-2041"} }' ``` ### Four ways in | Path | Best for | | --- | --- | | A2A `message:send` / `message:stream` | Full task records, provenance artifact, pipeline phases. | | OpenAI-compatible `/v1/chat/completions` | Existing OpenAI SDK, LangChain, LiteLLM, or Vercel AI code: change `base_url` and the key. | | `asha` command line | Setup, settings, questions, live checks, and the BAA from a terminal; one file, no dependencies. | | MCP server (`asha mcp`) | Claude Code, Codex, Cursor, Gemini CLI, VS Code: your coding agent calls Asha and reads these docs as tools. | Source: https://askasha.org/developers/docs/overview ## Drop-in with OpenAI SDKs `POST /v1/chat/completions` speaks the OpenAI Chat Completions wire format. Point any OpenAI SDK, LangChain, LiteLLM, or the Vercel AI SDK at `https://api.askasha.org/v1` with your Asha key and Asha answers, sources attached. ### Two settings | Setting | Value | | --- | --- | | `base_url` | `https://api.askasha.org/v1` | | `api_key` | Your Asha key (`dnai_a2a_...`) | | `model` | `asha` (plan default), `asha-base` (pin Base), `asha-auto` (Enterprise: stakes routing), `asha-apex` (Enterprise, non-streaming). `dnai/asha` and `asha-latest` are accepted too; responses label the model `dnai/`. | ```python from openai import OpenAI client = OpenAI(base_url="https://api.askasha.org/v1", api_key="YOUR_API_KEY") completion = client.chat.completions.create( model="asha", messages=[{"role": "user", "content": "Which antihypertensives are safe in pregnancy?"}], metadata={"audience": "clinician", "session_id": "visit-2041"}, ) print(completion.choices[0].message.content) print(completion.model_extra["dnai_meta"]["evidence_count"], "sources") ``` ### Request mapping | OpenAI field | What Asha does with it | | --- | --- | | `messages[-1]` (role `user`) | The question. Required; the last message must be a user turn. | | Earlier `user` / `assistant` turns | Passed to the engine as conversation history for this request. The endpoint is stateless per request; `metadata.session_id` pins a per-key identity so memory continuity follows your own session ids. | | `system` messages | Folded into the history as caller context. Asha's own system prompt, safety rules, and citations stay in force; this channel cannot switch them off. | | `metadata` | Asha options, same names as the A2A API: `session_id`, `audience` (`patient`, `caregiver`, `clinician`, `nurse`, `pharmacist`, `physician`), `persona`, `verbosity`, `emoji`, `memory: "off"`. Saved key settings apply when a field is absent (Customize your agent). | | `stream`, `stream_options.include_usage` | Server-sent events in the OpenAI chunk format; a final usage chunk when requested. `asha-apex` is non-streaming. | | `user` or header `X-DNAI-User` | Pins the memory identity for continuity (the original way, still honored). | | Header `X-DNAI-Sources: keep` | Keeps the trailing sources panel in the answer text. Off by default; sources and citations arrive in `dnai_meta` either way. | | `temperature`, `max_tokens`, `tools`, `response_format` | Accepted and ignored: the engine's gravity router sets sampling and calls its own evidence tools. | ### Response | Field | Meaning | | --- | --- | | `id`, `model` | `chatcmpl-...` and `dnai/`. | | `choices[0].message.content` | Asha's answer in Markdown. `finish_reason` is `stop`. | | `usage` | `prompt_tokens`, `completion_tokens`, `total_tokens`, plus `dnai_token_counts_estimated` when the engine did not report exact counts. | | `dnai_meta` | Extension object: `depth_requested`, `depth_served` (`base`, `mid`, `apex`), `evidence_count`, `citations[]` (up to 20), `task_gravity`. OpenAI SDKs keep unknown fields (Python: `completion.model_extra["dnai_meta"]`). | | Non-streaming transport | The body starts with whitespace bytes every 20 s while Asha works (valid JSON, keeps proxies open) and ends with the completion object. | | Streaming | `chat.completion.chunk` deltas; the chunk with `finish_reason: "stop"` carries `dnai_meta`. Comment lines (`: phase ...`, `: keep-alive`) report pipeline phases and keep proxies open; SDK parsers skip them. | | Errors | `{"error": {"message", "type", "code"}}` with the usual statuses (401, 403 `plan_required` for `asha-apex` outside Enterprise, 404 `model_not_found`, 429 with `Retry-After`, 500 `engine_error`), so SDKs raise their typed exceptions. | | `GET /v1/models` | Lists the models your key can call (`dnai/asha`, `dnai/asha-base`, `dnai/asha-auto`, `dnai/asha-apex` for Asha keys); `client.models.list()` works. | ### Node (streaming) ```javascript import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.askasha.org/v1", apiKey: "YOUR_API_KEY" }); const stream = await client.chat.completions.create({ model: "asha", stream: true, messages: [{ role: "user", content: "Red flags for pediatric fever?" }], }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ""); } ``` ### curl ```bash curl https://api.askasha.org/v1/chat/completions \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "asha", "messages": [{"role": "user", "content": "Red flags for pediatric fever?"}]}' ``` ### Limits of the compatibility layer | Item | Behaviour | | --- | --- | | Scope | A key from this site calls Asha and its tiers; other DNAi engine ids return 403. | | Depth | Self-serve plans run Base; `asha-auto` is pinned to Base and reported as such in `dnai_meta.depth_served`. Enterprise unlocks `asha-auto` and `asha-apex`. | | Tools and function calling | Not exposed. Asha runs its own retrieval tools server-side and returns the citations. | | Vision and audio | Not on this endpoint. Text parts only. | | Browser calls | The API is for servers. Cross-origin browser calls are refused; keep the key server-side. | | Metering | One query per request, same daily and monthly allowances as the A2A endpoints. | Source: https://askasha.org/developers/docs/openai ## Command line `asha` is a single-file, standard-library Python 3.8+ command line: set up in three steps, customize your agent, ask with streaming, run live checks, handle the BAA, and give your coding agent Asha as a tool over MCP. ### Install and set up: asha init `asha init` does three things: creates or reuses your key, saves how your agent answers (name, organization, tone, audience, length, emoji), and asks a first question so you see a cited answer. `asha init --yes --email you@company.com --name CareBot --verbosity brief` runs it without prompts. | Item | Value | | --- | --- | | Requirement | Python 3.8 or newer, `curl` or `wget`. No packages. | | Install location | `~/.local/bin/asha` (override with `ASHA_INSTALL_DIR`). | | Script | `https://askasha.org/cli/asha` (read it before you run it; it is one file) | | Key storage | `~/.config/asha/credentials.json`, mode 0600. `ASHA_API_KEY` and `--key` override it. | | Base URL | `ASHA_API_BASE` or `--base`; default `https://api.askasha.org`. | ```bash curl -fsSL https://askasha.org/cli/install.sh | sh asha init # 1 key, 2 customize your agent, 3 first answer asha ask "Which antihypertensives are safe in pregnancy?" --audience clinician ``` ### Commands | Command | What it does | | --- | --- | | `asha init [--email E] [--name N] [--org O] [--tone T] [--audience A] [--verbosity V] [--emoji E] [--no-test] [--yes]` | Three steps: key, saved settings, first answer. Prompts when run in a terminal; flags and `--yes` for scripts. | | `asha signup EMAIL [--name NAME] [--save]` | Creates a free Asha-only key (`product: asha`) and prints it once. | | `asha login [--key KEY]` | Verifies a key against `/api/a2a/usage` and saves it. | | `asha logout` | Removes the saved key. | | `asha ask "question" [--audience A] [--verbosity V] [--emoji E] [--name N --org O --tone T] [--session ID] [--depth base\|auto] [--model ID] [--no-memory] [--no-stream] [--json] [--verbose]` | Streams the answer, then prints the sources footer. Style flags override the saved settings for this call. `--json` prints the task; `--verbose` shows pipeline phases on stderr. Reads stdin when no question is given. | | `asha config show \| set key=value ... \| reset` | Reads or saves the key's defaults: `name`, `org`, `tone`, `audience`, `verbosity`, `emoji`, `memory`. An empty value clears one field; `name=` drops the white label. | | `asha test [--yes] [--json]` | Three live checks with their task ids: a grounded answer with sources, emergency routing for chest pain, and your saved length and emoji settings. Uses 3 queries. | | `asha mcp` | Runs the MCP server on stdio for coding agents (Use with your agent). | | `asha mcp add claude-code\|codex\|cursor\|gemini\|vscode\|claude-desktop\|other` | Prints the setup command or config for that agent, with the full path to `asha`. | | `asha usage`, `asha whoami` | Plan, scope, today's and this month's counts, remaining, tokens. | | `asha rotate [--yes] [--save]` | Replaces the key; the old key stops at once. | | `asha models` | Model ids for the OpenAI-compatible endpoint. | | `asha baa show [--md]` | The current agreement, its version and SHA-256, and PHI readiness. | | `asha baa accept --org --signer --title --email [--yes]` | Records acceptance for your account and prints the receipt. | | `asha baa status` | Acceptance state, whether you are on the current version, PHI mode, next step. | | `asha docs [topic]`, `asha version` | Docs URL, or the doc sections that match a topic (`asha docs errors`) from llms-full.txt; CLI version. | ### Customize from the terminal ```bash asha config set name=CareBot org="Acme Health" tone=warm audience=patient verbosity=brief emoji=off asha config show asha ask "Is it safe to take ibuprofen with lisinopril?" --verbosity detailed # one-call override asha config reset # answer as Asha again ``` ### Exit codes | Code | Meaning | | --- | --- | | 0 | Success. | | 1 | User-facing error (no key, HTTP error, cancelled prompt). Message on stderr, no traceback. | | 2 | `ask --no-stream` returned a task that did not complete, or `asha test` had a failing check. | | 130 | Interrupted. | Source: https://askasha.org/developers/docs/cli ## Customize your agent Choose how Asha answers your users: under your product's name or as Asha, for patients or clinicians, brief or detailed, with or without emoji. Save the settings on your key once, or send them per request. Emergency routing, crisis resources, refusals, and citations are the same under every setting. ### Settings | Setting | Values | Default | Effect | | --- | --- | --- | --- | | `persona.name` | Up to 32 characters, 4 words | None: answers as Asha | Asha presents itself under this name. Asked who built it, it says it is built on DNAi Systems intelligence. Titles and credentials (`Dr`, `MD`, `nurse`), instruction-shaped text, and DNAi agent names are rejected. | | `persona.organization` | Up to 60 characters, 8 words | None | Tells the user the service is presented by your organization. | | `persona.tone` | `warm`, `clinical`, `concise`, `friendly`, `formal` | Asha's own voice | Sets the voice of the answer. | | `audience` | `patient`, `caregiver`, `clinician`, `nurse`, `pharmacist`, `physician` | Read from the question | Plain language for patients and caregivers; peer-grade clinical answers for clinicians. | | `verbosity` | `brief`, `standard`, `detailed` | `standard` | `brief`: the answer itself is about 120 words and leads with what to do; red flags, follow-up questions, and the sources list still follow it. `standard`: Asha's usual length, which depends on the question. `detailed`: about 800 to 1,200 words under headings (evidence and its strength, options, risks, when to get care). Safety warnings and citations stay at every length. | | `emoji` | `off`, `none`, `on` | `off` | `off`: no expressive emoji; functional marks such as ✓ and ⚠ may appear. `none`: plain text only, with check and warning marks as text characters. `on`: up to two of Asha's marks in a reply, never in crisis, grief, clinician, caregiver, or document replies, and not in back-to-back replies. | | `memory` | `on`, `off` | `on` | `off`: no personal-memory read or write for the call. | ### Where to set them | Way | How | Applies to | | --- | --- | --- | | Saved on your key | `PUT /api/a2a/preferences`, `asha config set`, or the `asha_preferences` MCP tool | Every call with the key: `message:send`, `message:stream`, and `/v1/chat/completions`. | | Per request | `metadata` on the same three endpoints, same field names | That call. A request value wins over the saved value field by field; a request `persona` replaces the saved persona whole. | | `asha-apex` model | Enterprise only | Runs the benchmarked configuration unchanged; saved settings do not apply. | ### Endpoints | Method | Path | Behavior | | --- | --- | --- | | GET | `/api/a2a/preferences` | Returns `preferences` (what is saved), `effective` (saved values plus defaults), and `allowed` (every valid value). | | PUT | `/api/a2a/preferences` | Replaces the saved object. Send `{}` to reset. `asha config set` merges for you. Unknown fields return 422; a bad value returns 400 `invalid_params` with `param` naming the field. | | Either | Key type | Keys created on this site (self-service). Internal keys send the same fields in `metadata`. | ```bash curl -X PUT https://api.askasha.org/api/a2a/preferences \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"persona": {"name": "CareBot", "organization": "Acme Health", "tone": "warm"}, "audience": "patient", "verbosity": "brief", "emoji": "off"}' curl https://api.askasha.org/api/a2a/preferences -H "Authorization: Bearer YOUR_API_KEY" ``` ### From the command line ```bash asha config set name=CareBot org="Acme Health" tone=warm audience=patient verbosity=brief emoji=off asha config show asha ask "Is it safe to take ibuprofen with lisinopril?" --verbosity detailed # one-call override asha config reset # answer as Asha again ``` ### Per request ```json { "message": {"role": "user", "parts": [{"text": "Red flags for a fever in a 2-year-old?"}]}, "metadata": { "audience": "caregiver", "verbosity": "detailed", "emoji": "none", "persona": {"name": "CareBot", "organization": "Acme Health"} } } ``` ### What no setting changes | Rule | Under every setting | | --- | --- | | Emergencies | Chest pain, stroke signs, overdose, and similar get the instruction to call emergency services. | | Crisis | Self-harm and suicide questions get crisis resources (988 in the US) and no emoji. | | Evidence | Sources and citations are returned on every answer, in the text and in the provenance artifact. | | Identity | The agent says it is an AI and, when asked, that it is built on DNAi Systems. It never claims a credential. | | Privacy | Personally identifying patterns are redacted before storage. | Source: https://askasha.org/developers/docs/customize ## Use with your agent (MCP) `asha mcp` runs a Model Context Protocol server on your machine. Claude Code, Codex, Cursor, Gemini CLI, VS Code, and Claude Desktop can then ask Asha, read and save your settings, check the BAA, and search these docs while they build your product. ### Set up Install the CLI and run `asha init` once; the server reads the saved key, so no secret goes into your agent's config. `asha mcp add ` prints the line below with the full path filled in. | Agent | Command or config | | --- | --- | | Claude Code | `claude mcp add asha -- asha mcp` | | Codex | `codex mcp add asha -- asha mcp` | | Cursor | `{"mcpServers": {"asha": {"command": "asha", "args": ["mcp"]}}}` | | Gemini CLI | `gemini mcp add asha asha mcp` | | VS Code | `code --add-mcp '{"name":"asha","command":"asha","args":["mcp"]}'` | | Claude Desktop | `{"mcpServers": {"asha": {"command": "/Users/you/.local/bin/asha", "args": ["mcp"]}}}` | ```bash curl -fsSL https://askasha.org/cli/install.sh | sh asha init # saves your key; the MCP server reads it asha mcp add claude-code # prints the exact command for your agent claude mcp add asha -- asha mcp ``` ### Tools | Tool | What it does | Uses a query | | --- | --- | --- | | `ask_asha` | Asks Asha. Inputs: `question`, optional `audience`, `verbosity`, `emoji`, `session_id`, `memory`. Returns the cited answer, its sources, and the task id. | Yes | | `asha_usage` | Plan and queries remaining today and this month. | No | | `asha_preferences` | `get`, `set`, or `reset` the key's saved settings (Customize your agent). | No | | `asha_baa` | The BAA summary (version, SHA-256, PHI readiness), the full text, or this account's acceptance status. Read-only. | No | | `asha_docs` | Searches these docs by topic and returns the matching sections as Markdown. | No | ### Ask your agent | You say | What happens | | --- | --- | | Set up Asha for my app: call it CareBot for Acme Health, brief answers, no emoji. | `asha_preferences` saves the settings on your key. | | Use Asha to check whether ibuprofen interacts with lisinopril, for a patient. | `ask_asha` returns a cited answer your agent can quote and link. | | Write the backend call to Asha with retries. | `asha_docs` pulls the send, errors, and Idempotency-Key sections before your agent writes code. | | Where do we stand on the BAA? | `asha_baa` reports the version, whether you accepted it, and what blocks PHI mode. | ### BAA through an agent | Step | Who | | --- | --- | | Read the agreement and its SHA-256 | Your agent (`asha_baa`) or you (`asha baa show --md`). | | Check acceptance and PHI readiness | Your agent (`asha_baa` with `view: status`) or you (`asha baa status`). | | Accept | A person with authority to bind the organization, in a terminal: `asha baa accept --org ... --signer ... --title ... --email ...`. The MCP server has no accept tool. | ### Protocol | Item | Value | | --- | --- | | Transport | stdio, newline-delimited JSON-RPC 2.0. No network listener; logs go to stderr. | | Protocol versions | 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05 (negotiated at `initialize`). | | Capabilities | `tools`. Each tool declares an input schema and read-only or open-world hints. | | Errors | API errors come back as tool results with `isError: true` and the API's message, for example a daily limit with its reset. | ### Docs for agents without MCP | Document | URL | | --- | --- | | llms.txt (index) | `https://askasha.org/llms.txt` | | llms-full.txt (every page, one Markdown file) | `https://askasha.org/llms-full.txt` | | OpenAPI 3.1 | `https://api.askasha.org/openapi.json` | | Any page | The Copy page as Markdown button at the top of each docs page. | Source: https://askasha.org/developers/docs/agents ## Authentication and keys Keys are Bearer tokens with the prefix `dnai_a2a_`. A key is shown once at creation and stored server-side as a SHA-256 hash; nobody at DNAi can read it back. ### Create a key: POST /api/a2a/signup | Field | Type | Required | Meaning | | --- | --- | --- | --- | | `email` | string | yes | Account email. One account per address; a second signup returns 409. | | `name` | string | no | Your name or product name. | | `product` | string | no | `asha` for an Asha-only key (what this site sends). Default `dnai` mints a key for every public DNAi engine from dnai.systems. | | `tier` | string | no | Self-serve signup creates `free` keys only. Paid plans go through `/api/a2a/upgrade`. | | `hcaptcha_token` | string | conditional | Only when the server has captcha enabled. | ```bash curl -X POST https://api.askasha.org/api/a2a/signup \ -H "Content-Type: application/json" \ -d '{"email": "you@company.com", "name": "Your product", "product": "asha"}' ``` ### Signup response | Field | Meaning | | --- | --- | | `api_key` | The Bearer token. Save it now; it is never shown again. | | `key_prefix` | First 16 characters, used to identify the key in usage and task records. | | `tier` | `free`. | | `monthly_limit`, `daily_limit` | Query allowances for the plan. | | `spending_cap_usd` | Estimated-spend ceiling for paid plans (0 on free). | | `product` | `asha`. | | `scopes` | `["asha"]`: the agents this key may call. | ### Key lifecycle | Action | Call | Effect | | --- | --- | --- | | Check usage | `GET /api/a2a/usage` | Queries today and this month, limits, remaining, `scopes`, `product`. | | Rotate | `POST /api/a2a/rotate-key` | Returns a new key; the old key is invalid immediately. | | Suspend | Stripe `invoice.payment_failed` | Paid accounts pause on failed payment and resume on `invoice.paid`. | | Anti-abuse | Signup | 10 new keys per network address per 24 hours; more on request at hello@dnai.systems. | ```bash curl https://api.askasha.org/api/a2a/usage -H "Authorization: Bearer YOUR_API_KEY" curl -X POST https://api.askasha.org/api/a2a/rotate-key -H "Authorization: Bearer YOUR_API_KEY" ``` Source: https://askasha.org/developers/docs/authentication ## Send a message `POST /a2a/v1/message:send` runs Asha's full pipeline (retrieval, verification, synthesis) and returns the finished task in one response. Typical latency is 10 to 60 seconds depending on the question; use the streaming variant for a live UI. ### Request body | Field | Type | Required | Meaning | | --- | --- | --- | --- | | `message.role` | string | yes | `user`. | | `message.parts[]` | array | yes | At least one part with non-empty `text`. Parts are concatenated. Total text up to 500,000 characters. | | `agent_id` | string | no | `asha` or `health`. Defaults to Asha. Any other value returns 403 for a key from this site. | | `metadata` | object | no | Options below. Other keys are reserved; do not send them. | ### metadata options | Key | Values | Meaning | | --- | --- | --- | | `session_id` | string, up to 64 chars | Multi-turn continuity. Reuse the same id across calls and Asha keeps the conversation context. Longer values are truncated to 64 characters. | | `audience` | `patient`, `caregiver`, `consumer`, `principal`, `clinician`, `nurse`, `pharmacist`, `physician`, `hcp`, `professional`, `healthcare_professional` | Selects the register: plain-language patient answers or peer-grade clinical answers. `user_role` is accepted as a synonym. Unrecognized values are ignored. | | `depth` | `base`, `auto` | `base` (all self-serve plans) is one retrieval-grounded pass. `auto` (Enterprise) lets stakes routing escalate to a multi-model merge or an expert panel. Other values return 400. Every task reports `depth_served`. | | `persona` | object `{name, organization, tone}` | White label: Asha answers under your product's name and says it is built on DNAi Systems if asked. Names with credentials or instructions are rejected and the persona is dropped; the accepted name is echoed in `task.metadata.persona`. Safety rules, citations, and disclaimers stay in force. | | `memory` | `on`, `off` | `off` runs the call with no personal-memory read or write. Use for stateless or privacy-sensitive integrations. Default: one memory scope per key, never shared across keys. | | `verbosity` | `brief`, `standard`, `detailed` | Answer length. `brief` keeps the answer itself near 120 words; `detailed` aims for 800 to 1,200 words under headings. Default `standard`. Safety warnings and citations stay at every length (Customize your agent). | | `emoji` | `off`, `none`, `on` | `off` (default): no expressive emoji. `none`: plain text only. `on`: up to two of Asha's marks, never in crisis, grief, clinician, caregiver, or document replies. | ### Response: task | Field | Meaning | | --- | --- | | `task.id` | UUID. Use it with the tasks endpoints. | | `task.status.state` | `COMPLETED` or `FAILED`. | | `task.status.message` | On `FAILED`, an agent message whose text part is the error. | | `task.artifacts[0]` | `name: "response"`. `parts[0].text` is Asha's answer in Markdown. | | `task.artifacts[1]` | `name: "provenance"`. `parts[0].data` holds `sources[]`, `evidence_count`, `citations[]` (up to 20), `contract_hash`, `predicate_scope`, `model`. | | `task.metadata` | `agent_id`, `domain` (`health`), `caller` (your key prefix), `session_id` and `persona` when supplied, `input_tokens`, `output_tokens`, `evidence_count`, `citations` (up to 10), `sources` (up to 10), `depth_served` (`base`, `mid`, `apex`), `task_gravity`. | | `task.created_at`, `task.updated_at` | ISO 8601 timestamps (UTC). | ### Retries: Idempotency-Key | Header or case | Behavior | | --- | --- | | `Idempotency-Key` | Optional, 1 to 255 characters. Use a fresh UUID v4 per question and reuse it only when retrying that question. Never put personal data in it. | | Same key, same body, within 24 hours | Returns the saved response with `Idempotent-Replayed: true`. Asha does not run again and the allowance is not used again. | | Same key, different body | 400 `idempotency_key_reused`. | | Same key while the first call is still running | 409 `idempotency_in_progress` with `Retry-After: 5`. | | First call failed auth, limits, or validation | Nothing is saved; fix the request and retry with the same key. | | `Idempotency-Status: unavailable` | The retry store was unreachable; the call ran without retry protection. | | Streaming | Not supported on `message:stream`. After a dropped stream, fetch the result with `GET /a2a/v1/tasks/{task_id}`. | ### curl ```bash curl -X POST https://api.askasha.org/a2a/v1/message:send \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "asha", "message": { "role": "user", "parts": [{"text": "Which antihypertensives are safe in pregnancy?"}] }, "metadata": {"audience": "clinician", "session_id": "visit-2041"} }' ``` ### Python ```python import requests r = requests.post( "https://api.askasha.org/a2a/v1/message:send", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "agent_id": "asha", "message": {"role": "user", "parts": [{"text": "Which antihypertensives are safe in pregnancy?"}]}, "metadata": {"audience": "clinician", "session_id": "visit-2041"}, }, timeout=120, ) task = r.json()["task"] answer = task["artifacts"][0]["parts"][0]["text"] provenance = task["artifacts"][1]["parts"][0]["data"] print(answer) print(provenance["evidence_count"], "sources", task["metadata"]["depth_served"]) ``` ### JavaScript ```javascript const res = await fetch("https://api.askasha.org/a2a/v1/message:send", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ agent_id: "asha", message: { role: "user", parts: [{ text: "Which antihypertensives are safe in pregnancy?" }] }, metadata: { audience: "clinician", session_id: "visit-2041" }, }), }); const { task } = await res.json(); const answer = task.artifacts[0].parts[0].text; const provenance = task.artifacts[1].parts[0].data; ``` Source: https://askasha.org/developers/docs/send ## Stream a response `POST /a2a/v1/message:stream` takes the same body and auth as `message:send` and answers with `text/event-stream`: pipeline phases, text chunks as they are written, and a final task envelope. ### Events | Event | Data | When | | --- | --- | --- | | `task_created` | `{task_id, agent_id, state, created_at}` | Once, first frame. | | `phase` | `{name, elapsed_ms, ...}` | Each pipeline step (names below). | | `chunk` | `{text, elapsed_ms}` | Incremental answer text; concatenate in order. | | `heartbeat` | `{elapsed_ms}` | Every 8 seconds of silence; keeps proxies open. | | `task_completed` | `{task, artifacts, metadata}` | Once; same task shape as `message:send`. | | `task_failed` | `{error, task_id}` | Terminal on error. | | (no event) | `data: [DONE]` | Stream terminator; close the connection. | ### Phase names | Name | Payload | Meaning | | --- | --- | --- | | `retrieval_start` | | Evidence retrieval across the medical corpus begins. | | `retrieval_complete` | `evidence_count` | Retrieval finished, bounded at 25 seconds. | | `arena_start` | `candidate_count` | Claim competition begins (higher-stakes questions only). | | `arena_complete` | `winner_count` | Claims settled, bounded at 15 seconds. | | `synthesis_start` | | Answer generation begins; `chunk` events follow. | ### curl ```bash curl -N -X POST https://api.askasha.org/a2a/v1/message:stream \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"agent_id": "asha", "message": {"role": "user", "parts": [{"text": "Red flags for pediatric fever?"}]}}' ``` ### JavaScript (fetch + ReadableStream) ```javascript const res = await fetch("https://api.askasha.org/a2a/v1/message:stream", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ agent_id: "asha", message: { role: "user", parts: [{ text: "Red flags for pediatric fever?" }] } }), }); const reader = res.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; for (;;) { const { value, done } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const frames = buffer.split("\n\n"); buffer = frames.pop(); for (const frame of frames) { const event = (frame.match(/^event: (.*)$/m) || [])[1]; const data = (frame.match(/^data: (.*)$/m) || [])[1]; if (data === "[DONE]") return; if (event === "chunk") process.stdout.write(JSON.parse(data).text); } } ``` Source: https://askasha.org/developers/docs/stream ## Tasks Every call creates a task record you can fetch, list, or cancel. Tasks are scoped to your key: you see yours and nobody else's. ### Endpoints | Method | Path | Parameters | Notes | | --- | --- | --- | --- | | GET | `/a2a/v1/tasks/{task_id}` | | Served from cache, then PostgreSQL. 404 when unknown. | | GET | `/a2a/v1/tasks` | `offset` (default 0), `limit` (default 20, max 100), `state`, `agent_id` | Returns `{tasks[], total, offset, limit}`. | | POST | `/a2a/v1/tasks/{task_id}:cancel` | | 409 when the task already reached a terminal state. | ```bash curl "https://api.askasha.org/a2a/v1/tasks?state=COMPLETED&limit=20" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ### States | State | Meaning | | --- | --- | | `SUBMITTED` | Accepted, not started. | | `WORKING` | Pipeline running. | | `COMPLETED` | Answer and provenance attached. | | `FAILED` | Error text in `status.message`. | | `CANCELED` | Stopped by `:cancel`. | Source: https://askasha.org/developers/docs/tasks ## Plans, limits, and errors Plans set monthly and daily query allowances. Upgrades run through Stripe and return you to this site. ### Plans | Plan | Price | Queries | Daily | Spend cap | Depth | | --- | --- | --- | --- | --- | --- | | Free | $0 | 50 / month | 10 / day | None | `base` | | Developer | $49 / month | 1,000 / month | 200 / day | $100 | `base` | | Pro | $199 / month | 10,000 / month | 2,000 / day | $500 | `base` | | Enterprise | $999 / month | Unlimited | Unlimited | $5,000 | `base or auto` | ### Limits | Limit | Value | | --- | --- | | Requests per minute | Equal to your daily allowance, in a sliding 60-second window (free: 10). Exceeding it returns 429 with `Retry-After: 60`. | | Daily counter | Resets at midnight UTC. | | Monthly counter | Resets on the first of the month. | | Message size | 500,000 characters. | | Task list page | 100 tasks. | | Signups per network | 10 per 24 hours. | ### Upgrade and billing | Call | Body | Returns | | --- | --- | --- | | `POST /api/a2a/upgrade` | `{"tier": "developer" \| "pro" \| "enterprise"}` | `{checkout_url, tier}`. Stripe Checkout, then back to `askasha.org/developers?upgraded=true`. | | `GET /api/a2a/portal` | | `{portal_url}`: Stripe portal for invoices, card, and cancellation. | ### Error body | Field | Meaning | | --- | --- | | `error.type` | The cause, one value per row in the table below. Branch on this; it does not change. | | `error.code` | JSON-RPC 2.0 / A2A v1.0 number where a standard one exists, so related causes share a code. | | `error.message` | Readable explanation. Wording can change; do not parse it. | | `error.param` | The field or header the error is about, as a dotted path (`metadata.depth`, `message.parts`, `Idempotency-Key`). | | `error.doc_url` | Link to this error type in the reference. | | `error.request_id` | Same as the `X-Request-ID` response header. Quote it when you contact support. | | `error.retry_after` | Seconds until a retry can succeed (limits, some 409s and 503s). Also sent as the `Retry-After` header. | | `error.fields` | `validation_error` only: each failing field as `{loc, msg, type}`. | | `detail` | Older field, kept unchanged for existing clients. New code reads `error`. | | `Accept: application/problem+json` | Send this header to receive the same facts as RFC 9457 Problem Details (`type`, `title`, `status`, `detail`, `instance`, plus `code`, `error_type`, `request_id`, `param`, `retry_after`). | ### Errors | HTTP | `type` | `code` | Cause | | --- | --- | --- | --- | | 400 | `invalid_request` | `-32600` | Empty message, message over 500,000 characters, or a signup or billing field the API does not accept (email, `tier`, `product`, paid tier at signup, captcha). | | 400 | `invalid_params` | `-32602` | `metadata.depth` is neither `base` nor `auto`. | | 422 | `validation_error` | `-32602` | Body does not match the schema, for example `message` sent as a string instead of `{role, parts}`. | | 401 | `authentication_required` | `-32050` | No `Authorization: Bearer` header. | | 401 | `invalid_api_key` | `-32050` | Unknown, mistyped, or rotated key. | | 403 | `permission_denied` | `-32051` | Key has no access to the requested agent (Asha keys reach `asha` only). | | 403 | `account_suspended` | `-32051` | Failed payment. Fix it in the billing portal; usage, portal, and upgrade still work. | | 404 | `not_found` | `-32052` | No account or billing record for this key. | | 404 | `agent_not_found` | `-32052` | No public agent with this id. | | 404 | `task_not_found` | `-32001` | Unknown task, or a task created by another key. | | 409 | `conflict` | `-32053` | Signup: an account already exists for that email. Rotate the key instead. | | 409 | `task_not_cancelable` | `-32002` | Cancel on a task that already finished. | | 410 | `agent_retired` | `-32054` | The agent was retired and no longer answers. | | 400 | `idempotency_key_reused` | `-32055` | The `Idempotency-Key` was already used with a different body. Use a new key. | | 409 | `idempotency_in_progress` | `-32056` | The first call with this key is still running. Retry after `retry_after` seconds. | | 429 | `rate_limited` | `-32060` | Per-minute limit. `Retry-After: 60`. | | 429 | `daily_quota_exceeded` | `-32061` | Daily allowance used. Resets 00:00 UTC. | | 429 | `monthly_quota_exceeded` | `-32062` | Monthly allowance used. Resets on the 1st, or upgrade. | | 429 | `spending_cap_reached` | `-32063` | Spend cap for the month reached. | | 429 | `signup_rate_limited` | `-32064` | 10 new keys per network in 24 hours. | | 500 | `internal_error` | `-32603` | Unexpected error. Quote `error.error_id` to support. | | 503 | `service_unavailable` | `-32070` | Database or signup store briefly unavailable; retry in a few minutes. | Source: https://askasha.org/developers/docs/limits ## BAA, self-serve Read, accept, and check a Business Associate Agreement from the API or the command line. The agreement is versioned and hashed; your receipt proves the exact text you accepted. Status is stated, never implied: the current text is a draft pending counsel review, and PHI mode opens only when both gates below clear. ### Endpoints | Method | Path | Auth | Purpose | | --- | --- | --- | --- | | GET | `/api/a2a/baa` | None | Current agreement as JSON (`?format=md` Markdown, `?format=html` page): version, status, SHA-256, sections, subprocessors, PHI readiness. | | POST | `/api/a2a/baa/accept` | API key | Record acceptance for the key's account. Body: `organization`, `signer_name`, `signer_title`, `signer_email`, `attest_authority: true`, `accept_version` (current), optional `accept_sha256`. | | GET | `/api/a2a/baa/status` | API key | Latest acceptance, whether it matches the current version, `phi_allowed`, blockers, next step. | ```bash asha baa show --md # read the agreement (Markdown, with its SHA-256) asha baa accept --org "Acme Health" --signer "Jane Doe" --title CTO --email jane@acme.health asha baa status # receipt, version, PHI readiness, next step ``` ### Receipt | Field | Meaning | | --- | --- | | `acceptance_id`, `accepted_at` | Ledger row and timestamp (UTC). | | `baa_version`, `baa_sha256` | The exact text accepted. Compare with `GET /api/a2a/baa?format=md` at any time. | | `document_status` | Status of the text at acceptance, for example `DRAFT - Internal legal review complete ...`. | | `organization`, `signer` | Who bound whom; the signer attests authority. | | `phi_allowed` | Whether this key may send PHI now. | | `phi_readiness.blockers` | What still stands between acceptance and PHI mode. | ### PHI readiness: the two gates | Gate | Today | Clears when | | --- | --- | --- | | Agreement text effective | No: version 0.2-draft. Internal legal review against 45 CFR 164.504(e)(2) and 164.314(a)(2) complete 2026-09-29; awaiting principal ratification and an external flag-only read | The ratified text is published as v1.0 with `effective: true`; existing acceptances are asked to re-accept in one step. | | Model path inside a DNAi BAA | No: developer traffic runs on the direct Anthropic API, outside a BAA | PHI-designated keys route to the BAA-covered model path (Google Vertex today; Anthropic HIPAA organization pending). | | Result | `phi_allowed: false` for every account | Both gates true: `phi_allowed: true` on accepted, current-version accounts. | ### Subprocessors named in section 6 | Subprocessor | Role | BAA | | --- | --- | --- | | Google Cloud (Vertex AI) | Model inference for PHI-designated traffic | DNAi BAA in place | | Anthropic (direct API) | Model inference for non-PHI traffic (live default) | Outside a BAA; HIPAA organization pending | | Cloudflare | Edge, tunnel, TLS termination (transit only) | To be verified and published before PHI mode opens | | DNAi Systems infrastructure | Retrieval, memory, task and audit stores | First party; PHI-isolated vector store | ### Until PHI mode opens | Item | Rule | | --- | --- | | What you may send | De-identified queries. Personally identifying patterns are redacted before storage on every request regardless. | | Why accept now | Your acceptance is on record with a hash; when the effective version publishes you re-accept in one command instead of starting a paper process. | | Legal effect | None until the effective version is published. Requires review by your own counsel as well. | | Questions | hello@dnai.systems | ```bash curl https://api.askasha.org/api/a2a/baa?format=md curl -X POST https://api.askasha.org/api/a2a/baa/accept \ -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"organization": "Acme Health", "signer_name": "Jane Doe", "signer_title": "CTO", "signer_email": "jane@acme.health", "attest_authority": true, "accept_version": "0.2-draft"}' curl https://api.askasha.org/api/a2a/baa/status -H "Authorization: Bearer YOUR_API_KEY" ``` Source: https://askasha.org/developers/docs/baa ## Machine-readable documents These are the documents AI agents and tooling read. The tables below show what they contain so a person can check them without parsing JSON. ### Documents | Document | URL | Contents | | --- | --- | --- | | Asha agent card | `https://api.askasha.org/.well-known/agent-card.json?agent_id=asha` | A2A discovery document for Asha: interface URL, protocol version, security scheme, skills, epistemic capabilities. | | Directory card | `https://api.askasha.org/.well-known/agent-card.json` | Every public DNAi engine. Keys from this site call Asha only. | | OpenAPI 3.1 | `https://api.askasha.org/openapi.json` (also `/openapi.yaml`) | Generated from the running service; public developer paths only. Every operation has an operationId, examples, and its errors. | | API reference | `https://dnai.systems/api-reference` | The same document rendered for reading: every field, status code, error, and a curl sample per operation. | | llms.txt | `https://askasha.org/llms.txt` | Plain-text index of this API for language-model agents. | | llms-full.txt | `https://askasha.org/llms-full.txt` | Every docs page as one Markdown file, regenerated on each release. `asha docs ` and the `asha_docs` MCP tool search it. | | Corpus commitment | `https://api.askasha.org/api/audit/corpus-state/public` | Cryptographic hash over the knowledge corpus Asha answers from. | | Health | `https://api.askasha.org/a2a/v1/health` | `{status, agents, protocol}`; 503 when the engine is down. | | API terms | `https://api.askasha.org/api/a2a/terms?format=html` | Draft terms pending counsel review; JSON without the query string. | ### Asha agent card fields | Field | Value | | --- | --- | | `name` | Asha | | `version` | 2.0.0 | | `url` | `https://api.askasha.org/a2a/v1` | | `protocolVersion` | 1.0 | | `provider` | DNAi Systems, https://dnai.systems | | `defaultInputModes` | `text/plain`, `application/json` | | `defaultOutputModes` | `text/plain`, `application/json` | | `securitySchemes.bearer` | HTTP Bearer, format API-Key | | `epistemicCapabilities.provenanceInResponses` | true: sources and citations on every task | | `epistemicCapabilities.falsificationEndpoint` | `/api/feng/falsify` (JWT, Asha app accounts) | | `epistemicCapabilities.temporalQuerySupport` | true | | `epistemicCapabilities.evidenceGrounding` | CIU-grounded: retrieval, verification, Merkle audit | | `epistemicCapabilities.hallucinationMitigation` | Pre-generation verification and post-generation entity checks | ### Asha skills (from the agent card) | Skill id | Name | Example prompt | | --- | --- | --- | | `medical-qa` | Medical question answering | What are the latest treatment guidelines for type 2 diabetes? | | `drug-interaction-check` | Drug interaction check | Can a patient on warfarin safely take ibuprofen? | | `clinical-guidelines` | Clinical guideline lookup | USPSTF screening recommendations for colorectal cancer | | `evidence-synthesis` | Evidence synthesis | Summarize the evidence for ketamine in treatment-resistant depression | Source: https://askasha.org/developers/docs/discovery ## Scope and safety What a key from this site can reach, what Asha's answers are, and how your users' data is handled. ### Scope | Item | Rule | | --- | --- | | Agents | `asha` and its alias `health`. Every other agent id returns 403. | | Key scope field | `scopes: ["asha"]` on signup and usage responses. | | Depth | Self-serve plans run `base`. Enterprise keys may send `depth: "auto"`. | | Hosts | `https://api.askasha.org` is the canonical host for this API. | ### Clinical use | Item | Rule | | --- | --- | | What an answer is | Evidence-grounded medical information with sources. It is information, and a licensed clinician decides. | | Your product | Keep a clinician in the loop for diagnosis and treatment decisions. Show the sources Asha returns. | | Safety protocols | Crisis and self-harm handling, refusals, and disclaimers stay active under any `persona`. Do not strip them from the text you display. | | Terms | Draft API terms: `https://api.askasha.org/api/a2a/terms?format=html`. | ### Data handling | Item | Rule | | --- | --- | | Logging | Queries are logged for security, abuse prevention, and service improvement. | | PHI | Personally identifying patterns are redacted before a query is stored. Send `metadata.memory: "off"` to skip personal-memory read and write entirely. | | Memory scope | One memory per key. Nothing crosses between keys or between your users and Asha's consumer app. | | Sessions | `metadata.session_id` groups turns; omit it for independent questions. | | Privacy policy | `https://askasha.org/privacy` | Source: https://askasha.org/developers/docs/safety ## Changelog Every change to the developer API, newest first. Additive changes need no action; behavior changes say what to check. ### Versioning | Item | Value | | --- | --- | | Protocol | A2A v1.0. Every `/a2a/v1` response carries `A2A-Version: 1.0`. | | Additive changes | New fields, headers, error types, and endpoints ship without a version change. Clients must ignore fields they do not know. | | Behavior changes | Marked below with what to check. | ### Changes | Date | Change | Kind | | --- | --- | --- | | 2026-10-16 | Saved settings per key: `GET` and `PUT /api/a2a/preferences` for white-label name, organization, tone, audience, `verbosity`, `emoji`, and `memory`. They apply to `message:send`, `message:stream`, and `/v1/chat/completions`; request `metadata` overrides them. `persona` now works on `/v1/chat/completions` too. | Additive | | 2026-10-16 | `metadata.verbosity` (`brief`, `standard`, `detailed`) and `metadata.emoji` (`off`, `none`, `on`). | Additive | | 2026-10-16 | Streamed answers (`message:stream`, `/v1` with `stream: true`) now use `persona`, `verbosity`, and `emoji`, token by token. Before this, `persona` had no effect on streamed answers. Every answer also carries an identity rule so text in retrieved evidence cannot rename the agent. | Behavior change: streamed answers now use your persona | | 2026-10-16 | `asha` CLI 0.2: `init`, `config`, `test`, `docs `, and an MCP server (`asha mcp`) for Claude Code, Codex, Cursor, Gemini CLI, and VS Code. `llms-full.txt` publishes every docs page as one file. | Additive | | 2026-10-13 | Errors on every developer path carry `error` with `type`, `code`, `message`, `doc_url`, `request_id`, and `param` where relevant; `detail` is unchanged. Each limit has its own `type` with `Retry-After`. Task errors use A2A v1.0 codes (`-32001`, `-32002`). | Additive | | 2026-10-13 | `Idempotency-Key` on `message:send` makes retries safe. `Accept: application/problem+json` returns RFC 9457 Problem Details. | Additive | | 2026-10-13 | Usage, upgrade, portal, rotate-key, and BAA keep working after the allowance runs out or the account is suspended. | Behavior change: these routes no longer return 429 or 403 for limits | | 2026-10-13 | Non-integer `metadata.tau_min` or `metadata.tau_max` returns 400 `invalid_params` instead of 500. An unhandled 500 on a developer path puts the error object in `error` and its text in `detail`. | Behavior change: check code that reads `error` as a string on 500 | | 2026-10-13 | OpenAPI: stable operationIds, a curl sample per operation, per-operation security, and a rendered reference at dnai.systems/api-reference. | Additive | | 2026-10-12 | Task read and cancel are scoped to the key that created the task; other keys get 404. | Behavior change: tasks from another key are no longer visible | | 2026-10-12 | Optional Google OAuth bearer tokens for A2A (Gemini Enterprise). | Additive | | 2026-10-11 | OpenAPI YAML at `/openapi.yaml`; request schemas for `/v1/chat/completions` and BAA accept. | Additive | | 2026-09-29 | OpenAI-compatible streaming and metering, self-serve BAA, and the `asha` command-line tool. | Additive | | 2026-09-28 | Asha developer site and docs; keys minted on askasha.org are scoped to Asha. | Additive | | 2026-09-17 | Engine memory is scoped per key and never shared across keys. | Behavior change: earlier calls from other keys no longer inform answers | | 2026-09-16 | Domain keys (`health`, `fitness`, ...), `metadata.depth`, and the curated OpenAPI document. | Additive | | 2026-09-15 | Customer keys run Base depth; Mid and Apex need Enterprise. | Behavior change: `depth_served` reports what ran | Source: https://askasha.org/developers/docs/changelog