@yesilsci/health-ai-api
v0.1.1
Published
Official TypeScript client for the Yesil Health AI enterprise (B2B) API.
Downloads
258
Maintainers
Readme
@yesilsci/health-ai-api
Official TypeScript client for the Yesil Health enterprise (B2B) API.
Zero runtime dependencies — uses the platform fetch + ReadableStream
(Node ≥ 18, modern browsers, edge runtimes). The hard part of integrating —
parsing the typed Server-Sent Events stream — is handled for you.
Install
npm install @yesilsci/health-ai-apiQuick start
import { YesilHealthClient } from '@yesilsci/health-ai-api';
import { randomUUID } from 'node:crypto';
const client = new YesilHealthClient({
baseUrl: 'https://api.yesilhealth.com',
apiKey: process.env.YESIL_API_KEY!, // sent as X-API-Key
});
for await (const ev of client.chatStream({
question: 'Is metformin safe for a patient with stage 3 CKD?',
request_id: randomUUID(), // idempotent billing — strongly recommended
demographics: { age: 62, sex: 'female' },
health_context: 'eGFR 45 mL/min/1.73m². On lisinopril 10mg daily.',
})) {
if (ev.type === 'delta') process.stdout.write(ev.content);
}One-shot (no live rendering):
const { text, events } = await client.chat({ question: '...' });Authentication
Every request is authenticated with your enterprise API key via the X-API-Key
header. Keep it server-side; never ship it in a browser bundle or mobile app.
The event stream
chatStream() yields typed events. Route on event.type:
| type | Payload | Notes |
|--------------------|--------------------------------------|-------|
| meta | phase, conversation_id, research preview fields | Lifecycle + mid-stream research previews. |
| delta | content: string | Append content to build the answer text. |
| citation | citation fields | A literature citation for the answer. |
| graph | data: {...} | Structured chart/diagram, delivered out-of-band from text. |
| memory_extracted | signals: MemorySignal[] | Only if your tenant has extract_memory enabled. Persist and replay via memory. |
| done | summary: {...} | Terminal success event. |
| error | message, code | Terminal failure event; stream ends. |
Forward compatibility. The API only ever adds fields and event types within a contract version — it never renames, removes, or retypes existing ones. Always include a
defaultbranch in yourswitchand ignore unknown event types. This client surfaces them asUnknownEventrather than throwing.
Request fields
| Field | Required | Description |
|------------------------|----------|-------------|
| question | ✅ | The end-user's question. |
| request_id | — | Client UUID for idempotent billing. Strongly recommended. |
| demographics | — | Small structured profile (≤ 12 KB JSON). |
| health_context | — | Free-form clinical context (vitals, EHR summary, wearable rollups). |
| conversation_history | — | Last turns only (max 8), role ∈ user/assistant. |
| memory | — | Raw memory signals to replay. |
| tenant_id | — | Optional hint; must match the key's tenant. |
Errors
Non-2xx HTTP responses throw YesilApiError with status, code
(server error_code), and message:
import { YesilApiError } from '@yesilsci/health-ai-api';
try {
await client.chat({ question: '...' });
} catch (e) {
if (e instanceof YesilApiError) {
if (e.code === 'RATE_LIMITED') { /* back off */ }
if (e.status === 402) { /* quota exhausted / billing */ }
}
}Common codes: RATE_LIMITED (429), quota/billing (402), INVALID_API_KEY
(401). In-stream failures arrive as an error event (see table above), not an
exception, unless you use the chat() convenience wrapper which re-throws them.
Account endpoints
await client.billing(); // billing status
await client.quota(); // quota / rate-limit status
await client.usage(); // usage reportCancellation
Pass an AbortSignal to stop a stream early:
const ac = new AbortController();
setTimeout(() => ac.abort(), 5_000);
for await (const ev of client.chatStream({ question: '...' }, { signal: ac.signal })) { /* … */ }Versioning
The client targets contract v1 (/api/v1). When Yesil Health cuts a new
major version it ships alongside v1; bump apiVersion in ClientOptions to
migrate on your own schedule. v1 is never force-killed.
