# HebrewCore documentation

> HebrewCore by baba Hebrew (https://itsbaba.com) is a REST API for products that work in Hebrew: translation between Hebrew, English, Russian and more; protected translation that keeps prices, names, codes, numbers and dates exact, with general, finance, legal and clinical domains; ICU plural messages; account terms; render-ready RTL/LTR display; language detection for code-switched input; transliteration; nikud; and the Clinical API. Solution guides cover commerce, customer support, app localization, finance, legal, education and healthcare.

Base URL: https://hc.itsbaba.com. Authenticate every request (except GET /v1/health) with `Authorization: Bearer hc_live_…`. Requests and responses are JSON. Errors use `{ "error": { "type", "message", "code" } }`.

Web version: https://hc.itsbaba.com/docs · Interactive API reference: https://hc.itsbaba.com/reference · OpenAPI: https://hc.itsbaba.com/openapi.json · Full docs plus API reference: https://hc.itsbaba.com/llms-full.txt

## Contents

**Getting Started:** [Introduction](https://hc.itsbaba.com/docs/intro.md) · [Quickstart](https://hc.itsbaba.com/docs/quickstart.md) · [Authentication](https://hc.itsbaba.com/docs/auth.md) · [Dashboard Sign-In](https://hc.itsbaba.com/docs/dashboard-signin.md) · [Playground](https://hc.itsbaba.com/docs/playground.md)

**AI Agents:** [MCP Server](https://hc.itsbaba.com/docs/mcp.md)

**Core Concepts:** [Directionality](https://hc.itsbaba.com/docs/directionality.md) · [Protected Values](https://hc.itsbaba.com/docs/protection.md) · [Domains](https://hc.itsbaba.com/docs/domains.md) · [Quality Tiers](https://hc.itsbaba.com/docs/quality.md) · [Rate Limits & Quotas](https://hc.itsbaba.com/docs/limits.md) · [Plans & Pricing](https://hc.itsbaba.com/docs/pricing.md) · [Errors](https://hc.itsbaba.com/docs/errors.md) · [Privacy](https://hc.itsbaba.com/docs/privacy.md)

**Translation:** [POST /v1/translate](https://hc.itsbaba.com/docs/translate.md) · [Protected Translation](https://hc.itsbaba.com/docs/protected.md) · [Account Terms](https://hc.itsbaba.com/docs/terms.md) · [POST /v1/translate/batch](https://hc.itsbaba.com/docs/batch.md) · [App Localization: ICU Plurals](https://hc.itsbaba.com/docs/icu.md) · [POST /v1/transliterate](https://hc.itsbaba.com/docs/transliterate.md)

**Display & Detection:** [POST /v1/analyze](https://hc.itsbaba.com/docs/analyze.md) · [POST /v1/wrap](https://hc.itsbaba.com/docs/wrap.md) · [POST /v1/detect](https://hc.itsbaba.com/docs/detect.md)

**Hebrew Text:** [POST /v1/nikud](https://hc.itsbaba.com/docs/nikud.md) · [POST /v1/strip-nikud](https://hc.itsbaba.com/docs/strip-nikud.md)

**Solutions:** [Solutions](https://hc.itsbaba.com/docs/solutions.md) · [Commerce & Marketplaces](https://hc.itsbaba.com/docs/solution-commerce.md) · [Customer Support](https://hc.itsbaba.com/docs/solution-support.md) · [App Localization](https://hc.itsbaba.com/docs/solution-localization.md) · [Finance & Banking](https://hc.itsbaba.com/docs/solution-finance.md) · [Legal & Contracts](https://hc.itsbaba.com/docs/solution-legal.md) · [Education & Publishing](https://hc.itsbaba.com/docs/solution-education.md) · [Healthcare](https://hc.itsbaba.com/docs/solution-healthcare.md)

**Guides:** [Guide: Localizing an App or Site](https://hc.itsbaba.com/docs/guide-localization.md) · [Guide: Mixed-Direction Display](https://hc.itsbaba.com/docs/guide-display.md) · [Guide: Assistants and Chat](https://hc.itsbaba.com/docs/guide-assistants.md) · [Guide: Voice Output](https://hc.itsbaba.com/docs/guide-voice.md) · [Guide: Regulated Content](https://hc.itsbaba.com/docs/guide-regulated.md)

**Clinical API:** [Clinical API](https://hc.itsbaba.com/docs/medical.md) · [Access & Data Handling](https://hc.itsbaba.com/docs/medical-access.md) · [POST /v1/medical/translate](https://hc.itsbaba.com/docs/medical-translate.md) · [WebSocket /v1/medical/stream](https://hc.itsbaba.com/docs/medical-stream.md) · [POST /v1/medical/translate/stream](https://hc.itsbaba.com/docs/medical-sse.md) · [POST /v1/medical/query](https://hc.itsbaba.com/docs/medical-query.md) · [POST /v1/medical/verify](https://hc.itsbaba.com/docs/medical-verify.md)

**Reference:** [GET /v1/languages](https://hc.itsbaba.com/docs/languages.md) · [GET /v1/health](https://hc.itsbaba.com/docs/health.md) · [Status & Uptime](https://hc.itsbaba.com/docs/status.md) · [Machine-Readable Discovery](https://hc.itsbaba.com/docs/discovery.md)

## Introduction

HebrewCore by [baba Hebrew](https://itsbaba.com) is the language layer for products that work in Hebrew. One REST API covers translation between Hebrew, English, Russian and more; protected translation that keeps prices, product names, codes, numbers and dates exactly as written; render-ready right-to-left / left-to-right display for any surface; language detection for code-switched input; transliteration; and nikud for display and speech.

Teams use it for [commerce, customer support, app localization, finance, legal, education and healthcare](https://hc.itsbaba.com/docs#solutions). Four [domains](https://hc.itsbaba.com/docs#domains) (general, finance, legal and clinical) tune protection to the values and wording each field cannot afford to get wrong, and the [Clinical API](https://hc.itsbaba.com/docs#medical) adds streaming, record search and verification for health products.

The API speaks standard JSON over HTTPS. Every endpoint lives under one base URL:

```text
https://hc.itsbaba.com
```

> Prefer to explore interactively? The [API reference](https://hc.itsbaba.com/reference) renders the live OpenAPI 3.1 spec and lets you run authenticated calls in the browser. The [playground](https://hc.itsbaba.com/dashboard/playground) gives a guided UI for the most common calls.

## Quickstart

1. Create an API key in the [console](https://hc.itsbaba.com/dashboard/api-keys). 2. Send it as a bearer token on every request. 3. Call an endpoint:

```bash
curl https://hc.itsbaba.com/v1/translate \
  -H "Authorization: Bearer hc_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Welcome to your account", "target_lang": "he", "transliterate": true }'
```

### Node (fetch)

```js
const res = await fetch("https://hc.itsbaba.com/v1/translate", {
  method: "POST",
  headers: {
    "Authorization": "Bearer hc_live_YOUR_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ text: "Welcome to your account", target_lang: "he" }),
});
const data = await res.json();
console.log(data.translation.text, data.translation.dir); // "…", "rtl"
```

### Python (requests)

```python
import requests

r = requests.post(
    "https://hc.itsbaba.com/v1/translate",
    headers={"Authorization": "Bearer hc_live_YOUR_KEY"},
    json={"text": "Welcome to your account", "target_lang": "he"},
)
print(r.json()["translation"]["text"])
```

## Authentication

Machine-to-machine requests authenticate with an **API key** sent as a bearer token. Keys come in two modes, `hc_live_…` and `hc_test_…`. Both work the same way, with the same limits and billing; use test keys to keep development traffic separate.

```http
Authorization: Bearer hc_live_…
```

Keys are shown once at creation and stored only as a hash. Create, name, and revoke them in the dashboard. The dashboard itself signs in with an email one-time code; the API never uses that session, only the bearer key.

An account can hold several active keys at once, which is how you rotate without downtime: create a new key, deploy it to your servers, confirm traffic has moved (the dashboard shows each key's last use), then revoke the old one. A revoked key stops working within 30 seconds.

> Treat keys as secrets. Use them from your server, never from untrusted client code or a device. Rotate immediately if one is exposed. The API accepts TLS 1.2 or newer only.

## Dashboard Sign-In

The [console](https://hc.itsbaba.com/dashboard) is where you create and revoke API keys, see usage, and manage [account terms](https://hc.itsbaba.com/docs#terms). Sign in with your email address: we send a one-time code, and you type it in. There is no password and no magic link.

Access is by invitation. Only invited email addresses can sign in; ask your HebrewCore contact to add a colleague. Colleagues on the same team share one account: the same keys, account terms, usage and limits. The dashboard session is separate from the API: API calls always authenticate with a bearer key.

## Playground

The [playground](https://hc.itsbaba.com/dashboard/playground) runs the API from the browser with a guided form: translation, protected translation, batches, display, detection, transliteration, nikud, account terms and, when your account has it, the Clinical API.

| Rule | Detail |
| --- | --- |
| Sign-in | Requires [dashboard sign-in](https://hc.itsbaba.com/docs#dashboard-signin) with the email one-time code. No API key is needed or stored in the browser. |
| Quota and rate limit | Runs on your account's own monthly character quota and per-minute rate limit, exactly like an API call, with the same validation and response headers. |
| Request size | 4,000 characters per request, across all text fields. |

Use synthetic data only in the playground, since it runs in your browser. Send real patient data only from your server with an API key.

## MCP Server

HebrewCore is also a remote [Model Context Protocol](https://modelcontextprotocol.io) server, so AI agents and assistants can call every capability as a tool. Each tool call runs the matching REST endpoint with your key, so validation, rate limits, the monthly character quota, account terms and Clinical access work exactly as they do over REST.

| Setting | Value |
| --- | --- |
| Endpoint | `https://hc.itsbaba.com/mcp` |
| Transport | Streamable HTTP (JSON responses, no session). Protocol versions `2026-07-28`, `2025-11-25`, `2025-06-18` and `2025-03-26`. |
| Authentication | Your API key as the header `Authorization: Bearer hc_live_…`. Listing the tools works without a key; calling one needs it. |
| Server card | [`/.well-known/mcp.json`](https://hc.itsbaba.com/.well-known/mcp.json) (also at `/.well-known/mcp/server-card.json`) |
| Registry name | `com.itsbaba/hebrewcore` |

### Tools

| Tool | What it does |
| --- | --- |
| `translate` | One text between Hebrew, English, Russian and more, with protected values, domains, gender and ICU plurals |
| `translate_batch` | Up to 50 strings to one target language |
| `analyze_direction` | RTL/LTR structure and display runs of a string or a record (free) |
| `detect_language` | Dominant language, script and per-language segments (free) |
| `wrap_for_display` | Render-ready HTML, isolates or marks for one display line (free) |
| `transliterate` | Hebrew to Latin letters, or Latin spelling to Hebrew letters |
| `add_nikud` | Full vowel points, verified |
| `strip_nikud` | Remove nikud and cantillation (free) |
| `list_languages` | Supported languages and their codes (free) |
| `list_terms` | The account's protected terms (free) |
| `add_terms` | Add or update protected terms (free) |
| `delete_term` | Delete one protected term (free) |
| `clinical_translate` | Clinical English to verified Hebrew (Clinical access) |
| `clinical_query` | Hebrew clinical question to an English record query (Clinical access) |
| `clinical_verify` | Check Hebrew against its English clinical source (Clinical access) |
| `health` | Service health; needs no key |

Tools marked free use no characters; the rest use the monthly character quota like the endpoint they call. Protected values (prices, amounts, account numbers, dates, doses, codes, product names) come back exactly as written, and the server tells the agent not to change them. API errors such as `quota_exceeded`, `rate_limited` or `scope_required` come back as tool errors with the same message.

### Claude Code

```text
claude mcp add --transport http hebrewcore https://hc.itsbaba.com/mcp \
  --header "Authorization: Bearer hc_live_YOUR_KEY"
```

### Claude Desktop and claude.ai

The server authenticates with a static API key, and Claude custom connectors that only offer OAuth cannot send it. Connect Claude Desktop through `mcp-remote`, which adds the header. In `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "hebrewcore": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://hc.itsbaba.com/mcp", "--header", "Authorization:${HC_AUTH}"],
      "env": { "HC_AUTH": "Bearer hc_live_YOUR_KEY" }
    }
  }
}
```

The same `mcp-remote` setup works for any client that cannot send a header itself.

### Cursor

In `~/.cursor/mcp.json` or the project's `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "hebrewcore": {
      "url": "https://hc.itsbaba.com/mcp",
      "headers": { "Authorization": "Bearer hc_live_YOUR_KEY" }
    }
  }
}
```

### VS Code

In `.vscode/mcp.json`. VS Code asks for the key once and stores it securely:

```json
{
  "inputs": [
    { "type": "promptString", "id": "hebrewcore-key", "description": "HebrewCore API key", "password": true }
  ],
  "servers": {
    "hebrewcore": {
      "type": "http",
      "url": "https://hc.itsbaba.com/mcp",
      "headers": { "Authorization": "Bearer ${input:hebrewcore-key}" }
    }
  }
}
```

### OpenAI API and Agents SDK

As a remote MCP tool in the Responses API:

```text
from openai import OpenAI

client = OpenAI()
response = client.responses.create(
    model="gpt-5.5",
    tools=[{
        "type": "mcp",
        "server_label": "hebrewcore",
        "server_url": "https://hc.itsbaba.com/mcp",
        "headers": {"Authorization": "Bearer hc_live_YOUR_KEY"},
        "require_approval": "never",
    }],
    input="Translate 'Your order of 3 items ships on 04/03/2026' into Hebrew, keeping the date and quantity exact.",
)
print(response.output_text)
```

With the OpenAI Agents SDK (Python):

```text
from agents import Agent, HostedMCPTool

agent = Agent(
    name="Hebrew assistant",
    tools=[HostedMCPTool(tool_config={
        "type": "mcp",
        "server_label": "hebrewcore",
        "server_url": "https://hc.itsbaba.com/mcp",
        "headers": {"Authorization": "Bearer hc_live_YOUR_KEY"},
        "require_approval": "never",
    })],
)
```

> Keep the key on your side: in a config file on your machine, a secret store, or your server. Never put it in a prompt, a shared configuration or browser code. Clinical tools also need a key with Clinical access and refuse calls that come from a browser.

## Directionality

The defining feature of HebrewCore is structured directionality. For any string, the API returns:

| Field | Description |
| --- | --- |
| `dir` | Paragraph base direction, `"rtl"` or `"ltr"`. With `base:"auto"` this follows the Unicode first-strong rule, matching CSS `dir="auto"`. |
| `mixed` | `true` when the text contains both strong RTL and strong LTR characters (invisible bidi marks and digits do not count). |
| `lang` | Best-effort BCP-47 language from the dominant script (e.g. `he`, `en`). |
| `script` | Dominant ISO-15924 script (`Hebr`, `Latn`, `Arab`, …). |
| `runs[]` | Maximal same-direction segments in logical order. Each run has `text`, `dir`, `script`, `lang`, `start`, and `end` (UTF-16 offsets, `end` exclusive, so `text.slice(start,end)` reproduces the run). |

Example: `"שלום world"` resolves to two runs you can render independently:

- `שלום`: rtl · he · Hebr · 0–5
- `world`: ltr · en · Latn · 5–10

For display, use `display_runs` or `/v1/wrap`. They keep every left-to-right unit whole, so a price, a range such as "10–20%", a date, a model number or a comparison such as "<5" never splits or mirrors inside a Hebrew line.

`/v1/analyze`, `/v1/detect`, `/v1/wrap`, and `/v1/strip-nikud` are deterministic, run with no language model, and do not consume your character quota.

## Protected Values

Some text must never change in translation: prices and currency, quantities, dates, order and account numbers, product and brand names, codes, interface variables, and in regulated fields doses, units and lab values. HebrewCore finds these values, replaces each with a placeholder the model cannot alter, and restores the original afterwards. It then checks every sentence: each protected value and every number must come back unchanged, and negation, left/right and grammatical gender must match. A sentence that cannot be verified is returned in its source language, flagged, rather than translated wrongly. Each [domain](https://hc.itsbaba.com/docs#domains) adds its own values and checks.

| Protected automatically | Examples |
| --- | --- |
| Numbers, amounts and signs | `$129.99`, `₪149.90`, `10–20%`, `<5`, `2 ×` |
| Dates and times | `04/03/2026` (rewritten so it cannot be misread), `08:30` |
| Identifiers and contact details | order and account numbers, emails, phone numbers, URLs |
| Interface markup | `{name}`, `{{count}}`, `%s`, `<keep>…</keep>` |
| Your terms | [Account terms](https://hc.itsbaba.com/docs#terms), plus `protected_terms` and `glossary` entries on the request: product names, brand names, drug names, legal terms |
| Financial values, with `domain: "finance"` | IBANs, SWIFT/BIC, bank account and card numbers, Israeli ID numbers, invoice and policy numbers, rates and basis points |
| Legal references, with `domain: "legal"` | clause and section references, defined terms, statute and case citations |
| Clinical terms, with `domain: "clinical"` | drug names, doses, units, lab values, clinical codes and abbreviations |

## Domains

`domain` on `/v1/translate` and `/v1/translate/batch` tells protected translation what kind of text it is reading, so it knows which values to lock and which meaning changes to reject. There are four domains. `general` is the default; any other value turns protection on by itself, so you do not need `protect: true`.

| Domain | Use it for | Also protects | Extra checks |
| --- | --- | --- | --- |
| `general` *(default)* | Product, commerce, support, interface and everyday content. | The [standard set](https://hc.itsbaba.com/docs#protection): numbers, amounts, dates, identifiers, contact details, interface variables and your terms. | Every protected value and number comes back unchanged; negation, left/right and grammatical gender must match. |
| `finance` | Statements, payment and transfer notices, invoices, lending, insurance. Formal financial register. | IBANs (any country, including Israel), SWIFT/BIC codes, Israeli bank account numbers such as `12-345-678901`, Israeli ID numbers (9 digits with a check digit), card numbers (masked or full; the model only ever sees a placeholder), invoice, reference, policy and transaction numbers, signed currency amounts, percentages, basis points, interest rates and dates. | Direction words must match: credit/debit, deposit/withdrawal, increase/decrease, gain/loss, buy/sell, owe/are owed. Negation and every number are checked. |
| `legal` | Contracts, terms of service, privacy policies, notices and filings. Legal register. | Clause and section references: the label is translated and the number kept exactly (`Section 4.2` becomes `סעיף 4.2`; `Clause 7(b)`, `סעיף 12(א)` and `Article III` work the same way, and `§ 3` is kept whole). Defined terms (a Capitalized Term in quotes, or defined as `("the Company")`): translated once and used the same way in every later sentence, for example `(להלן: "החברה")`. Statute and case citations, kept as written (a Hebrew statute year such as `התשנ"ט-1999` becomes `5759-1999` in English and Russian). Party names you pass in `protected_terms`, dates and amounts. | Modality must match: shall/must against may, shall not/must not against may not, and will. Negation, numbers and references must be unchanged. |
| `clinical` | Patient instructions, care-team messages, clinical notes. Clinical register, for a clinician or a patient. | Drug names, doses, units, lab values, clinical codes and abbreviations. | The general checks with every drug, dose and lab value verbatim. `audience` and `patient_gender` apply. For streaming, record search and verification, use the [Clinical API](https://hc.itsbaba.com/docs#medical). |

A sentence that fails a check is retried once with a stronger model, told what was wrong. If it still fails, it comes back in the source language with `status: "fallback"` and an entry in `issues`, so a flipped "credit" or a "may" that became "shall" never reaches your users.

### Span Types

Every protected value is listed in `protection.spans` with a `type`. Personal and account data (`name`, `account`, `id_number`, `card`) is listed without a `value`, so it never appears in your logs through the response.

| Domain | Span types |
| --- | --- |
| Every domain | `term`, `glossary`, `number`, `ordinal`, `date`, `identifier`, `email`, `url`, `template` (interface variables), `keep`, `markup`, `code_inline`, `name` (redacted) |
| `finance` | `account` (IBAN, SWIFT/BIC, bank account), `id_number`, `card`, `reference` (invoice, policy, transaction). Amounts, percentages and basis points are `number`. |
| `legal` | `clause` (`value` is the number), `defined_term` (with its `render` in the target language), `citation` |
| `clinical` | `drug`, `dose`, `abbreviation`, `code` |

### Example: A Transfer Notice

```http
POST /v1/translate
{
  "text": "We debited ₪12,450.00 from account 12-345-678901 on 03/04/2026. Your interest rate increases by 0.25% to 4.75%.",
  "source_lang": "en",
  "target_lang": "he",
  "domain": "finance",
  "date_order": "DMY"
}

{
  "translation": {
    "text": "חייבנו את חשבון 12-345-678901 בסך ₪12,450.00 ב־3 באפריל 2026. שיעור הריבית שלך עולה ב־0.25% ל־4.75%.",
    "dir": "rtl",
    "protection": {
      "status": "ok",
      "spans": [
        { "type": "number", "value": "₪12,450.00" },
        { "type": "account" },
        { "type": "date", "value": "03/04/2026", "render": "3 באפריל 2026", "ambiguous_date": true },
        { "type": "number", "value": "0.25%" },
        { "type": "number", "value": "4.75%" }
      ],
      "issues": [],
      …
    },
    …
  }
}
```

## Quality Tiers

Translation and transliteration accept an optional `quality` parameter that trades latency for depth. Direction analysis, detection, and the language list are deterministic and instant.

| quality | When to use |
| --- | --- |
| `fast` | High volume and short strings, lowest latency. |
| `balanced` *(default)* | The default. Excellent quality for everyday use. |
| `smartest` | Maximum nuance for long or sensitive content. |

With [protected translation](https://hc.itsbaba.com/docs#protected), every tier runs the value and number checks; `balanced` and `smartest` add an independent review of each sentence for meaning changes.

## Rate Limits & Quotas

| Limit | Default | Notes |
| --- | --- | --- |
| Request rate | 600 requests / minute per account, across all its keys, on every plan | Exact sliding one-minute window. Returns `429 rate_limited` with a `Retry-After` header in seconds. See `X-RateLimit-*` headers. |
| Monthly characters | Set by your plan (100,000 on Free) | Counts billed characters: input characters times the weight of the endpoint and quality tier (see [Plans & Pricing](https://hc.itsbaba.com/docs#pricing)). Direction, detection, wrap, strip nikud, languages and account terms are not counted. Past the limit, counted requests return `429 quota_exceeded` until the next month or a plan change. |
| Per-request size | 20,000 chars (5,000 for transliterate, 10,000 for nikud, 2,000 for a clinical query) | Analyze accepts up to 100 fields, 20,000 chars total. |

### Response Headers

| Header | On | Meaning |
| --- | --- | --- |
| `X-Usage-Chars-Used` | `translate`, `translate/batch`, `transliterate`, `nikud` | Billed characters used this month by the account, including this request. |
| `X-Usage-Chars-Limit` | `translate`, `translate/batch`, `transliterate`, `nikud` | The account's monthly character quota, in billed characters. |
| `X-RateLimit-Limit` | Authenticated requests | Requests allowed per minute for the key. |
| `X-RateLimit-Remaining` | Authenticated requests | Requests left in the current minute. |
| `X-Content-Stored` | Every endpoint that takes text | Always `false`: HebrewCore never stores the text you send or the result. |
| `Server-Timing` | Authenticated requests | Time spent on our side: `auth`, `ratelimit` and `total`, in milliseconds. |
| `Cache-Control` | Clinical API | Always `no-store`. |

Every metered response includes usage headers:

```http
X-Usage-Chars-Used: 46
X-Usage-Chars-Limit: 100000
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599
X-Content-Stored: false
```

The response body reports both amounts: `usage.characters` is the length of the input, and `usage.billed_characters` is what the request counted toward the monthly quota. A 23-character protected translation at `balanced` returns:

```text
"usage": { "characters": 23, "billed_characters": 46 }
```

Key revocations and plan changes take effect within 30 seconds.

Authenticated responses also carry a `Server-Timing` header with the time spent on our side, so you can tell it apart from network time when you measure latency from your own region:

```http
Server-Timing: auth;desc="memory";dur=0, ratelimit;dur=0, total;dur=842
```

## Plans & Pricing

Every plan includes the full API. Plans differ only in how many characters you can use each month. Every plan is by inquiry: [request access](https://hc.itsbaba.com/pricing) and we set up your account and arrange payment with you directly. Nothing is charged online.

| Plan | Price | Monthly characters |
| --- | --- | --- |
| Free | $0 | 100,000 |
| Starter | $49 / month | 1,000,000 |
| Growth | $249 / month | 6,000,000 |
| Business | $999 / month | 30,000,000 |
| Enterprise | Custom | Custom |

### Every Plan Includes

- Translation between Hebrew, English and Russian
- Protected translation
- Domains: general, finance, legal and clinical
- ICU plurals
- Batch translation
- Directionality analysis
- Language detection
- Render-ready wrap
- Transliteration
- Nikud
- Account terms
- Playground
- Clinical API, on request
- 600 requests per minute
- 2,000 protected terms

### How Characters Are Counted

Billed characters are input characters times a weight. The weight depends on the endpoint and, for translation, the quality tier and whether the request is protected. Protected means any protection field, a [domain](https://hc.itsbaba.com/docs#domains), [account terms](https://hc.itsbaba.com/docs#terms) that apply, or `message_format: "icu"`.

| Weight | Applies to |
| --- | --- |
| Not counted | Direction, detection, wrap, strip nikud, languages, account terms |
| 1× | Translation (fast or balanced), transliteration, protected translation at fast |
| 2× | Protected translation at balanced |
| 3× | Nikud, the Clinical API, and translation at smartest |
| 5× | Protected translation at smartest |

### At the Limit

When the monthly characters are used up, counted requests return `429` with `quota_exceeded` until the next month starts or the plan changes. The `X-Usage-Chars-Used` and `X-Usage-Chars-Limit` headers and `usage.billed_characters` in each response show where you are. To change plans, contact us with the form on the [pricing page](https://hc.itsbaba.com/pricing) or from Plans in the console.

## Errors

All errors use one envelope with a stable `type`:

```json
{ "error": { "type": "rate_limited", "message": "…", "code": "rate_limited" } }
```

| Status | type | Meaning |
| --- | --- | --- |
| `400` | invalid_request | Malformed body or parameters. |
| `401` | unauthorized | Missing, invalid, or revoked API key. |
| `403` | forbidden | The key lacks a scope (`scope_required`), a Clinical call came from a browser (`server_only`), or TLS is older than 1.2 (`tls_version`). |
| `404` | not_found | No such route, or no such account term. |
| `429` | rate_limited / quota_exceeded | Burst limit or monthly character quota. |
| `500` | internal | Unexpected error. Safe to retry. |
| `502` | bad_gateway | Upstream model error. Nothing is charged. Safe to retry. |
| `503` | service_unavailable | A model feature is temporarily unavailable. |

`code` refines `type` where it helps, for example `unsupported_language` and `same_language` on protected translation, `invalid_message_format` for ICU input that does not parse, `terms_limit` on account terms, and `upstream_error` on `502`. Branch on `type` and `code`, never on `message`.

## Privacy

> The text you send and the text returned are **never stored**. We keep usage counts only (characters and request totals per day). Responses carry `X-Content-Stored: false`. This is how the service works, not a formal compliance certification; contact us for specific requirements.

Model-backed endpoints call the language-model provider directly over TLS with storage turned off, never through a model reseller or a logging gateway. API data is not used to train models. Contact us for the current subprocessor list and processing regions.

## POST /v1/translate

`POST /v1/translate`

Translate text and attach directionality metadata to both the source and the result.

| Parameter | Type | Description |
| --- | --- | --- |
| `text` *required* | string | 1–20,000 characters. |
| `target_lang` *required* | string | BCP-47 code, e.g. `he` or `en`. |
| `source_lang` | string | BCP-47 code or `"auto"` (default). |
| `transliterate` | boolean | Include a Latin transliteration of a Hebrew result. Default `false`. |
| `quality` | enum | `fast` · `balanced` (default) · `smartest`. |
| `gender` | enum | `male` · `female` · `general`, where the language marks it. |
| `message_format` | enum | `icu`: the text is an ICU MessageFormat string, and plural branches are rewritten for the target language. See [ICU plurals](https://hc.itsbaba.com/docs#icu). |
| `store` | boolean | Accepted for compatibility and has no effect. HebrewCore never stores request or response text. |

### Response

```json
{
  "id": "txn_…",
  "source": {
    "text": "Welcome to your account",
    "lang": "en", "dir": "ltr", "mixed": false, "script": "Latn",
    "runs": [ { "text": "Welcome to your account", "dir": "ltr", "script": "Latn", "lang": "en", "start": 0, "end": 23 } ]
  },
  "translation": {
    "text": "ברוכים הבאים לחשבון שלך",
    "transliteration": "Bruchim haba'im lakheshbon shelkha",
    "lang": "he", "dir": "rtl", "mixed": false, "script": "Hebr",
    "runs": [ { "text": "ברוכים הבאים לחשבון שלך", "dir": "rtl", "script": "Hebr", "lang": "he", "start": 0, "end": 22 } ]
  },
  "quality": "balanced",
  "usage": { "characters": 23 }
}
```

## Protected Translation

Add any of the fields below to `/v1/translate` or `/v1/translate/batch` to translate with [protected values](https://hc.itsbaba.com/docs#protection). Every sentence is checked before it is returned; one that cannot be verified comes back in the source language with `status: "fallback"`, so an unverified translation never reaches your users. Available between Hebrew (`he`), English (`en`) and Russian (`ru`).

| Parameter | Type | Description |
| --- | --- | --- |
| `protect` | boolean | Turn protection on. Implied by any field below, and by [account terms](https://hc.itsbaba.com/docs#terms) for Hebrew, English and Russian pairs. |
| `domain` | enum | `general` (default) for product, commerce, support and interface text · `finance` · `legal` · `clinical`. Each adds its own protected values, register and checks; see [Domains](https://hc.itsbaba.com/docs#domains). Any value except `general` implies `protect`. |
| `listener_gender` | enum | `male` · `female`. Who "you" is: `תרצי` / `תרצה`. Hebrew and Russian mark it; English does not. |
| `speaker_gender` | enum | `male` · `female`. Who "I" is, for an assistant or brand voice: `מצאתי`, `я нашла` / `я нашёл`. |
| `patient_gender` | enum | Clinical domain: a patient referred to in the third person. |
| `protected_terms` | string[] | Terms kept exactly as written: product names, brand names, SKUs. Up to 500. Added to the account terms for this request. |
| `redact_terms` | string[] | Kept exactly and never shown to the model: customer names and other personal data. Up to 200. |
| `glossary` | object | Source term → required rendering in the target language. Up to 500. |
| `date_order` | enum | How to read ambiguous numeric dates: `MDY` (US style) or `DMY` (Israel, Europe). Default: MDY for English sources, DMY for Hebrew and Russian. |
| `date_style` | enum | `hebrew` (default) spells the month out in the target language ("4 במרץ 2026", "4 марта 2026 г."); `iso`; `keep` (unambiguous dates only). |
| `audience` | enum | Clinical register: `clinician` (default) or `patient`. |
| `bidi` | enum | `isolate` wraps protected values in Unicode isolates in Hebrew output. Default `none`; see [/v1/wrap](https://hc.itsbaba.com/docs#wrap). |

### Quality with Protection

| Quality | What runs |
| --- | --- |
| `fast` | The deterministic checks on every sentence (protected values, numbers, signs, negation, left/right, gender), with a retry by a stronger model and fallback. Lowest latency: suited to live chat and voice. |
| `balanced` | The same, plus an independent model review of every sentence for meaning changes (negation, certainty, timing, quantities in words, who is being described). |
| `smartest` | As balanced, with the strongest model translating. |

### Example: A Shopping Assistant Replying in Hebrew

```bash
curl https://hc.itsbaba.com/v1/translate \
  -H "Authorization: Bearer hc_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "I found your order #A-10234: 2 × Wireless Earbuds Pro for $129.99. Would you like me to schedule delivery for 04/03/2026?",
    "source_lang": "en",
    "target_lang": "he",
    "protect": true,
    "protected_terms": ["Wireless Earbuds Pro", "A-10234"],
    "listener_gender": "female",
    "speaker_gender": "female",
    "quality": "fast"
  }'
```

```json
{
  "translation": {
    "text": "מצאתי את ההזמנה שלך מס׳ A-10234: 2 יחידות של Wireless Earbuds Pro במחיר $129.99. האם תרצי שאקבע את המשלוח ל־3 באפריל 2026?",
    "dir": "rtl",
    "protection": {
      "status": "ok",
      "source_lang": "en",
      "spans": [
        { "type": "term", "value": "A-10234" },
        { "type": "number", "value": "2" },
        { "type": "term", "value": "Wireless Earbuds Pro" },
        { "type": "number", "value": "$129.99" },
        { "type": "date", "value": "04/03/2026", "render": "3 באפריל 2026", "ambiguous_date": true }
      ],
      "issues": [],
      "segments": [
        { "source": "I found your order #A-10234: 2 × Wireless Earbuds Pro for $129.99.", "text": "מצאתי את ההזמנה שלך מס׳ A-10234: 2 יחידות של Wireless Earbuds Pro במחיר $129.99.", "status": "ok" },
        { "source": "Would you like me to schedule delivery for 04/03/2026?", "text": "האם תרצי שאקבע את המשלוח ל־3 באפריל 2026?", "status": "ok" }
      ]
    },
    …
  }
}
```

### Example: A Support Reply in Russian

```http
POST /v1/translate
{ "text": "Your refund of €45.00 was issued on 12/05/2026. I could not find any other open requests.",
  "target_lang": "ru", "protect": true, "speaker_gender": "female", "date_order": "DMY", "quality": "fast" }

→ "Возврат средств в размере €45.00 был оформлен 12 мая 2026 г. Я не нашла других открытых запросов."
```

## Account Terms

Account terms are a persistent, per-account list of names that must never change in translation: drug names, product names, brand names. Add them once, in the dashboard or with the endpoints below, and every protected translation on the account keeps them exactly as written: `/v1/translate`, `/v1/translate/batch` and the [Clinical API](https://hc.itsbaba.com/docs#medical), for every key.

| Behavior | Detail |
| --- | --- |
| Kept exactly | Every term is kept exactly as written. When a term has a rendering for the target language in `translations` (for example `translations.he`), that exact rendering is used instead. |
| Placeholder masking | Terms are replaced with placeholders before the model runs and restored afterwards, so the model never sees them and cannot alter them. This is stronger than an instruction in a prompt. |
| Automatic protection | When the account has terms, protection switches on automatically for Hebrew, English and Russian pairs. You do not need `protect: true`. |
| Per-request fields | `protected_terms` and `glossary` still work and add to the account list. When both name the same term, the request's entry wins. |
| Limits | 2,000 terms per account. A term or rendering is up to 200 characters, a note up to 500. `translations` accepts `he`, `en` and `ru`. |
| Propagation | Changes apply to new requests within 30 seconds. |

### The Term Object

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Identifier, used to delete the term. |
| `term` | string | The name, exactly as it must appear. |
| `translations` | object | Optional required rendering per target language: `{ "he"?, "en"?, "ru"? }`. |
| `note` | string \| null | Your own note, for example why the term is protected. |
| `created_at` | string | ISO 8601 timestamp. |

### POST /v1/terms

`POST /v1/terms`

Add or update terms. The body is `{ "terms": [{ "term", "translations"?, "note"? }] }`. Terms are upserted by exact term text: sending an existing term replaces its `translations` and `note`. Returns the stored terms and their `count`.

```bash
curl https://hc.itsbaba.com/v1/terms \
  -H "Authorization: Bearer hc_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "terms": [
      { "term": "Wireless Earbuds Pro" },
      { "term": "Optalgin", "translations": { "he": "אופטלגין", "ru": "Оптальгин" }, "note": "brand name" }
    ]
  }'
```

```json
{
  "terms": [
    { "id": "3f2c1a9e-8b7d-4c6e-9f10-2a3b4c5d6e7f", "term": "Optalgin",
      "translations": { "he": "אופטלגין", "ru": "Оптальгин" }, "note": "brand name",
      "created_at": "2026-01-15T09:30:00.000Z" },
    { "id": "7a1d2e3f-4b5c-4d6e-8f90-1a2b3c4d5e6f", "term": "Wireless Earbuds Pro",
      "translations": {}, "note": null,
      "created_at": "2026-01-15T09:30:00.000Z" }
  ],
  "count": 2
}
```

### GET /v1/terms

`GET /v1/terms`

List the account's terms, sorted by term, with the account `limit`.

```http
GET /v1/terms

{ "terms": [ { "id": "3f2c…", "term": "Optalgin", "translations": { "he": "אופטלגין" }, "note": "brand name", "created_at": "…" }, … ],
  "limit": 2000 }
```

### DELETE /v1/terms/{id}

`DELETE /v1/terms/{id}`

Delete one term. Returns `404 not_found` when the id does not belong to the account.

```http
DELETE /v1/terms/3f2c1a9e-8b7d-4c6e-9f10-2a3b4c5d6e7f

{ "deleted": true }
```

### Effect on a Translation

With the two terms above on the account, a plain request is protected automatically:

```http
POST /v1/translate
{ "text": "Take Optalgin with water. Wireless Earbuds Pro ships tomorrow.", "target_lang": "he" }

→ "יש ליטול אופטלגין עם מים. Wireless Earbuds Pro נשלח מחר."
```

## POST /v1/translate/batch

`POST /v1/translate/batch`

Translate many strings to one target language in a single request, for example to localize a set of UI strings or content fields. Up to 50 items, each up to 5,000 characters.

| Parameter | Type | Description |
| --- | --- | --- |
| `items` *required* | string[] | 1–50 strings to translate. |
| `target_lang` *required* | string | Applies to every item. |
| `source_lang`, `transliterate`, `quality`, `gender`, `message_format` | varies | Same as `/v1/translate`; applied to all items. With `message_format: "icu"`, each item is one ICU message. |
| Protection fields | varies | Any [protected translation](https://hc.itsbaba.com/docs#protected) field; each item then carries its own `protection` block. A protected batch carries at most 20,000 characters in total. Interface variables such as `{count}` and `%s` are kept in place. |

```json
{ "results": [ /* TranslationBlock per item, in input order */ ], "usage": { "characters": 18 } }
```

```http
POST /v1/translate/batch
{
  "items": ["{count} items in your cart", "Checkout", "Last updated %s ago"],
  "target_lang": "he",
  "protect": true,
  "glossary": { "Checkout": "לתשלום" }
}

→ ["{count} פריטים בעגלת הקניות שלך", "לתשלום", "עודכן לאחרונה לפני %s"]
```

## App Localization: ICU Plurals

Interface strings with plurals cannot be translated word for word: English has two plural forms, Hebrew has a separate form for two, and Russian has four. Set `message_format: "icu"` on `/v1/translate` or `/v1/translate/batch` and send an ICU MessageFormat string. You get back a valid ICU MessageFormat string in the target language, ready for your i18n library (FormatJS, i18next ICU, ICU4J, Android and Apple string catalogs that accept ICU).

| Rule | Detail |
| --- | --- |
| Arguments | `{name}`, `{count, number}` and `{date, date, short}` are kept exactly. |
| Plural branches | `plural` and `selectordinal` branches are rewritten for the target language's CLDR plural categories. Exact matches such as `=0` and `=1` are kept when the source has them. |
| `#` | Kept wherever the source used it. |
| `select` | Branch keys (`female`, `male`, `other`) are kept; each branch is translated. |
| Nesting | Nested messages are supported, for example a `select` inside a `plural` branch. |
| Validation | The input is parsed first: invalid ICU returns `400 invalid_request` with code `invalid_message_format`. The output is parsed and validated before it is returned; if it cannot be made valid, the source string comes back with `protection.status: "fallback"`. |
| Response | The usual translate response. `translation.text` is the ICU string. In a batch, every item is one message. |

### Plural Categories

| Language | Categories | Example for `{count}` days |
| --- | --- | --- |
| English (`en`) | `one`, `other` | 1 day · 2 days · 5 days |
| Hebrew (`he`) | `one`, `two`, `other` | 1 יום · 2 ימים · 5 ימים |
| Russian (`ru`) | `one`, `few`, `many`, `other` | 1 день · 2 дня · 5 дней · 1,5 дня |

### English to Hebrew

```http
POST /v1/translate
{
  "text": "{count, plural, one {# day left in your trial} other {# days left in your trial}}",
  "source_lang": "en",
  "target_lang": "he",
  "message_format": "icu"
}

{
  "translation": {
    "text": "{count, plural, one {נותר # יום לתקופת הניסיון} two {נותרו # ימים לתקופת הניסיון} other {נותרו # ימים לתקופת הניסיון}}",
    "lang": "he", "dir": "rtl",
    …
  },
  "usage": { "characters": 82 }
}
```

### English to Russian, with an Exact Match

```http
POST /v1/translate
{ "text": "{count, plural, =0 {Your cart is empty} one {# item in your cart} other {# items in your cart}}",
  "target_lang": "ru", "message_format": "icu" }

→ "{count, plural, =0 {Ваша корзина пуста} one {# товар в корзине} few {# товара в корзине} many {# товаров в корзине} other {# товара в корзине}}"
```

### Select Messages

```http
POST /v1/translate
{ "text": "{gender, select, female {{name} invited you to her workspace} male {{name} invited you to his workspace} other {{name} invited you to their workspace}}",
  "target_lang": "he", "message_format": "icu", "listener_gender": "female" }

→ "{gender, select, female {{name} הזמינה אותך לסביבת העבודה שלה} male {{name} הזמין אותך לסביבת העבודה שלו} other {{name} הזמינו אותך לסביבת העבודה}}"
```

> Without `message_format: "icu"`, arguments such as `{count}` are still protected, but plural branches are translated as plain text and keep the source language's categories. Always set it for ICU strings.

## POST /v1/analyze

`POST /v1/analyze`

Directionality only, with no language model. Pass exactly one of `text` (a single string) or `fields` (a map of name → string, ideal for annotating a whole record at once). Optional `base` is `auto` (default), `ltr`, or `rtl`.

Each analysis has two run lists. `runs` are exactly what the Unicode Bidirectional Algorithm resolves, including its known defects: in a Hebrew line, a range such as "10–20%" splits around the dash and "<5" can mirror. `display_runs` keep every left-to-right unit whole (a Latin term, a price, a number with its unit, a range, a date, a percentage, a comparison). Render `display_runs`, or use `/v1/wrap`.

### Single String

```bash
curl https://hc.itsbaba.com/v1/analyze \
  -H "Authorization: Bearer hc_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"שלום world"}'
```

### Field Map

```bash
curl https://hc.itsbaba.com/v1/analyze \
  -H "Authorization: Bearer hc_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "title":    "מסמך Q3 ready",
      "subtitle": "Read the summary"
    }
  }'
```

```json
{
  "fields": {
    "title":    { "dir": "rtl", "mixed": true,  "lang": "he", "script": "Hebr",
                  "runs": [ {"text":"מסמך ","dir":"rtl",...}, {"text":"Q3 ready","dir":"ltr",...} ] },
    "subtitle": { "dir": "ltr", "mixed": false, "lang": "en", "script": "Latn", "runs": [ … ] }
  }
}
```

## POST /v1/wrap

`POST /v1/wrap`

Render-ready bidirectional output for a display line. Every left-to-right unit (a Latin term, a price, a number with its unit, a range such as "10–20%", a date, a percentage, a comparison such as "<5") is kept whole and in order, so no digit, range or sign is ever reversed or mirrored. Deterministic, no model.

| Parameter | Type | Description |
| --- | --- | --- |
| `text` *required* | string | The display line, up to 20,000 characters. |
| `format` | enum | `html` (default, for the web, React and webviews): a `<span dir>` for the line and one per unit. `isolate`: Unicode isolates, for modern text engines (iOS, Android 7+, current browsers). `marks`: direction marks (LRM/RLM), which render correctly on every engine, including older Android and embedded displays. |
| `base` | enum | Paragraph direction of the surface: `auto` (default, first strong letter), `rtl` or `ltr`. Pass `rtl` for a Hebrew line even when it starts with a Latin term; `isolate` and `marks` output then starts with a mark so a text view takes the right direction by itself. |

```http
POST /v1/wrap   { "text": "הנחה: 10–20% על Galaxy S25 עד 31/12", "format": "html", "base": "rtl" }

{
  "dir": "rtl",
  "format": "html",
  "output": "<span dir=\"rtl\">הנחה: <span dir=\"ltr\" lang=\"und\">10–20%</span> על <span dir=\"ltr\" lang=\"en\">Galaxy S25</span> עד <span dir=\"ltr\" lang=\"und\">31/12</span></span>",
  "runs": [ … ]
}
```

## POST /v1/detect

`POST /v1/detect`

Detect the dominant language, script and base direction of a string, with a segment per language (no model). Built for short, code-switched input such as chat messages, search queries and voice transcripts: a brand, product name or acronym inside a Hebrew or Russian sentence ("PayPal", "iPhone", "API") does not change the dominant language, and Hebrew prefixes joined by a hyphen ("ה-API") are split correctly. Links and email addresses are ignored. Latin script is tagged `en`.

```http
POST /v1/detect   { "text": "Можно оплатить через PayPal сегодня?" }

{
  "lang": "ru", "script": "Cyrl", "dir": "ltr", "confidence": 0.941,
  "segments": [
    { "text": "Можно оплатить через ", "start": 0, "end": 21, "script": "Cyrl", "lang": "ru" },
    { "text": "PayPal ", "start": 21, "end": 28, "script": "Latn", "lang": "en" },
    { "text": "сегодня?", "start": 28, "end": 36, "script": "Cyrl", "lang": "ru" }
  ],
  "languages": [ { "lang": "ru", "share": 0.941 }, { "lang": "en", "share": 0.059 } ]
}
```

## POST /v1/transliterate

`POST /v1/transliterate`

Transliterate between scripts. `direction: "he-to-latin"` (default) romanizes Hebrew; `direction: "latin-to-he"` converts Latin spelling into Hebrew letters (useful for name entry and search). `text` up to 5,000 characters.

```http
POST /v1/transliterate   { "text": "שלום" }
{ "text": "שלום", "transliteration": "shalom", "scheme": "general", "direction": "he-to-latin" }
```

## POST /v1/nikud

`POST /v1/nikud`

Add full nikud (vowel points) to Hebrew text: for vocalized display, learning materials, and text-to-speech, where unvocalized Hebrew is ambiguous. `text` up to 10,000 characters. English terms and numbers are left untouched, and the result is checked: `verified: true` means removing the points gives back your text (only the vowel letters ו and י may differ, which does not change pronunciation). When `verified` is false, `nikud` is your text unchanged; send it to speech unvocalized or retry.

```http
POST /v1/nikud   { "text": "שלום עולם" }
{ "text": "שלום עולם", "nikud": "שָׁלוֹם עוֹלָם", "verified": true }
```

## POST /v1/strip-nikud

`POST /v1/strip-nikud`

Remove nikud, dagesh, and cantillation marks (keeping punctuation like the maqaf). Useful for normalization, search keys, and de-duplication. Deterministic, no model.

```http
POST /v1/strip-nikud   { "text": "שָׁלוֹם" }
{ "text": "שָׁלוֹם", "stripped": "שלום" }
```

## GET /v1/languages

`GET /v1/languages`

List supported languages with display names and direction.

```json
{ "languages": [ { "code": "he", "name": "Hebrew", "native": "עברית", "dir": "rtl" }, … ] }
```

## GET /v1/health

`GET /v1/health`

Liveness and database check. Public, no authentication required.

```json
{ "status": "ok", "db": "ok", "version": "1.0.0" }
```

## Status & Uptime

Live status, 90-day uptime per component and incident history are at [hc-status.itsbaba.com](https://hc-status.itsbaba.com). The page runs separately from the API, so it stays up during an outage. Checks run every minute (translation every five minutes) from outside the API.

- [`GET https://hc-status.itsbaba.com/api/status`](https://hc-status.itsbaba.com/api/status): current status as JSON, for your own monitoring. `status` is `operational`, `degraded`, `partial_outage` or `major_outage`.
- [`/feed.atom`](https://hc-status.itsbaba.com/feed.atom): incidents and their updates as an Atom feed (also [`/feed.json`](https://hc-status.itsbaba.com/feed.json)).
- [`GET /v1/health`](https://hc.itsbaba.com/docs#health): a direct liveness and database check against the API itself.

```bash
curl https://hc-status.itsbaba.com/api/status
{ "status": "operational", "updated_at": "…",
  "components": [ { "id": "api", "name": "API", "status": "operational", "latency_ms": 142, "uptime_90d": 99.998 }, … ],
  "active_incidents": [] }
```

## Machine-Readable Discovery

Tools and AI agents can find everything about the API from a few standard files. All are public and need no key.

| Path | What it is |
| --- | --- |
| [`/.well-known/api-catalog`](https://hc.itsbaba.com/.well-known/api-catalog) | API catalog (RFC 9727, `application/linkset+json`) linking the OpenAPI document, docs, llms.txt, status and the MCP server. The home page also sends `Link: </.well-known/api-catalog>; rel="api-catalog"`. |
| [`/apis.json`](https://hc.itsbaba.com/apis.json) | APIs.json index with the OpenAPI, documentation, pricing, status, llms.txt and MCP links. |
| [`/openapi.json`](https://hc.itsbaba.com/openapi.json) | The OpenAPI 3.1 document for every endpoint. |
| [`/llms.txt`](https://hc.itsbaba.com/llms.txt) | An index of the docs as Markdown for language models, with [`/llms-full.txt`](https://hc.itsbaba.com/llms-full.txt) holding everything in one file. |
| [`/sitemap.xml`](https://hc.itsbaba.com/sitemap.xml) | Every public page and Markdown file, referenced from [`/robots.txt`](https://hc.itsbaba.com/robots.txt). |

## Solutions

The same API serves very different products. Each guide below lists the endpoints and fields to use, a realistic request and response, and the mistakes teams make most often. All examples use synthetic data.

| Solution | Typical content | Start with |
| --- | --- | --- |
| [Commerce & Marketplaces](https://hc.itsbaba.com/docs#solution-commerce) | Listings, catalogs, promotions, checkout | `/v1/translate/batch`, account terms, `/v1/wrap` |
| [Customer Support](https://hc.itsbaba.com/docs#solution-support) | Assistant replies, macros, ticket text | `/v1/detect`, `/v1/translate` at `quality: "fast"` |
| [App Localization](https://hc.itsbaba.com/docs#solution-localization) | String files, ICU plurals, interface copy | `/v1/translate/batch` with `message_format: "icu"` |
| [Finance & Banking](https://hc.itsbaba.com/docs#solution-finance) | Statements, transfer notices, policies | `domain: "finance"` |
| [Legal & Contracts](https://hc.itsbaba.com/docs#solution-legal) | Contracts, terms, notices | `domain: "legal"` |
| [Education & Publishing](https://hc.itsbaba.com/docs#solution-education) | Lessons, readers, audio, textbooks | `/v1/nikud`, `transliterate` |
| [Healthcare](https://hc.itsbaba.com/docs#solution-healthcare) | Patient instructions, care-team messages | `domain: "clinical"`, the Clinical API |

## Commerce & Marketplaces

Product titles, descriptions, promotions and checkout copy in Hebrew and Russian, with every price, size, model number and brand name exactly as your catalog has it.

### What to Use

| Need | Use |
| --- | --- |
| Translate a catalog | `/v1/translate/batch` with `protect: true`, up to 50 items per call. |
| Brand, product and program names | [Account terms](https://hc.itsbaba.com/docs#terms) once for the whole catalog; `protected_terms` for one-off names. |
| Your house vocabulary | `glossary`, for example `"warranty": "אחריות"`. |
| Price and range lines on screen | `/v1/wrap` or `display_runs`, so `₪149.90` and `3–5` never split or mirror. |
| Search in Hebrew and Latin letters | `/v1/detect` on the query, `/v1/transliterate` for Latin-letter search keys. |

### Example

```http
POST /v1/translate/batch
{
  "items": [
    "Wireless Earbuds Pro, 2 pack",
    "Free shipping on orders over $50",
    "Only {stock} left in stock",
    "Model WEP-2210-BLK, 1-year warranty"
  ],
  "target_lang": "he",
  "protect": true,
  "protected_terms": ["Wireless Earbuds Pro"],
  "glossary": { "warranty": "אחריות" }
}

{
  "results": [
    { "text": "Wireless Earbuds Pro, מארז של 2", "lang": "he", "dir": "rtl", "protection": { "status": "ok", … } },
    { "text": "משלוח חינם בהזמנות מעל $50", "lang": "he", "dir": "rtl", "protection": { "status": "ok", … } },
    { "text": "נותרו רק {stock} במלאי", "lang": "he", "dir": "rtl", "protection": { "status": "ok", … } },
    { "text": "דגם WEP-2210-BLK, אחריות לשנה", "lang": "he", "dir": "rtl", "protection": { "status": "ok", … } }
  ],
  "usage": { "characters": 131 }
}
```

### Pitfalls

- **Unusual model names.** Codes with digits are protected automatically; a plain-word product name ("Nimbus", "Aurora") is not. Add it to account terms.
- **Prices in a Hebrew line.** `dir="rtl"` alone can split a range or move a sign. Render `display_runs` or the `/v1/wrap` output.
- **Batch size.** A protected batch carries at most 20,000 characters in total; split long descriptions across calls.

## Customer Support

Support assistants, macros and agent replies in the customer's language, with the assistant's voice and the customer's gender right, and every amount, date and order number unchanged.

### What to Use

| Need | Use |
| --- | --- |
| Know the customer's language | `/v1/detect` on the incoming message. Brands and product names inside it do not change the result. |
| Translate the reply | `/v1/translate` with protection at `quality: "fast"` for live chat, `balanced` for email. |
| Gendered Hebrew and Russian | `speaker_gender` for the assistant (`я нашла`, `מצאתי`) and `listener_gender` for the customer. |
| Customer names and personal data | `redact_terms`: kept exactly and never shown to the model. |
| Plan and feature names | [Account terms](https://hc.itsbaba.com/docs#terms). |

### Example

```http
POST /v1/translate
{
  "text": "Hi Olga, your refund of €45.00 for order #B-20931 was issued on 12/05/2026. I could not find any other open requests.",
  "source_lang": "en",
  "target_lang": "ru",
  "redact_terms": ["Olga"],
  "speaker_gender": "female",
  "listener_gender": "female",
  "date_order": "DMY",
  "quality": "fast"
}

{
  "translation": {
    "text": "Здравствуйте, Olga! Возврат средств в размере €45.00 по заказу #B-20931 был оформлен 12 мая 2026 г. Я не нашла других открытых запросов.",
    "lang": "ru", "dir": "ltr",
    "protection": {
      "status": "ok",
      "spans": [
        { "type": "number", "value": "€45.00" },
        { "type": "identifier", "value": "B-20931" },
        { "type": "date", "value": "12/05/2026", "render": "12 мая 2026 г.", "ambiguous_date": true }
      ],
      …
    }
  }
}
```

### Pitfalls

- **Unknown gender.** Leave `listener_gender` unset rather than guessing; Hebrew then uses neutral forms where it can.
- **Ambiguous dates.** `12/05/2026` is May 12 or December 5. Set `date_order` to match where the date came from.
- **Fallback sentences.** When a sentence returns `status: "fallback"`, show it in the source language or rephrase; never retranslate it without the checks.

## App Localization

String files for iOS, Android and the web, with interface variables intact and plurals rewritten for Hebrew and Russian. Translate at build time and ship the results with your app.

### What to Use

| Need | Use |
| --- | --- |
| Plurals and selects | `message_format: "icu"`, described in [ICU plurals](https://hc.itsbaba.com/docs#icu). |
| Many strings at once | `/v1/translate/batch`, one message per item, up to 50 per call. |
| Variables and markup | Kept automatically: `{name}`, `{{count}}`, `%s`, `%d`, and anything inside `<keep>…</keep>`. |
| Consistent product vocabulary | `glossary` and [account terms](https://hc.itsbaba.com/docs#terms). |
| Mixed-direction strings | `/v1/wrap` with `format: "isolate"` for iOS and Android, `html` for the web. |

### Example

```http
POST /v1/translate/batch
{
  "items": [
    "{count, plural, one {# new message} other {# new messages}}",
    "{days, plural, one {Your trial ends in # day} other {Your trial ends in # days}}",
    "Welcome back, {name}!"
  ],
  "source_lang": "en",
  "target_lang": "he",
  "message_format": "icu",
  "glossary": { "trial": "תקופת ניסיון" }
}

{
  "results": [
    { "text": "{count, plural, one {# הודעה חדשה} two {# הודעות חדשות} other {# הודעות חדשות}}", … },
    { "text": "{days, plural, one {תקופת הניסיון מסתיימת בעוד # יום} two {תקופת הניסיון מסתיימת בעוד # ימים} other {תקופת הניסיון מסתיימת בעוד # ימים}}", … },
    { "text": "ברוך שובך, {name}!", … }
  ],
  "usage": { "characters": 146 }
}
```

### Pitfalls

- **Hebrew has a form for two.** A Hebrew string file without a `two` branch shows the wrong form for 2. Let `message_format: "icu"` add it.
- **Keys are not text.** Send only the values, never the string keys, and map results back by position.
- **Buttons and labels.** Without `listener_gender`, Hebrew labels use the neutral infinitive (להציג עוד), which is usually what an interface wants.

## Finance & Banking

Statements, transfer and payment notices, loan and insurance documents, where an amount, an account number or the word "credit" must never change.

### What to Use

| Need | Use |
| --- | --- |
| Financial protection and register | `domain: "finance"`, described in [Domains](https://hc.itsbaba.com/docs#domains). |
| Statement lines | `/v1/translate/batch`, one line per item. |
| Customer names | `redact_terms`. Card numbers are replaced by placeholders automatically. |
| Israeli dates | `date_order: "DMY"` for dates written day first. |
| Amount lines in Hebrew | `/v1/wrap`, so `-$84.20` keeps its sign on the left. |

### Example

```http
POST /v1/translate/batch
{
  "items": [
    "Card payment, card ending 4821: -$84.20",
    "Interest credited: +$3.15 (APR 4.5%)",
    "Overdraft fee reversed on 03/04/2026",
    "Transfer to IBAN GB29 NWBK 6016 1331 9268 19"
  ],
  "source_lang": "en",
  "target_lang": "he",
  "domain": "finance"
}

{
  "results": [
    { "text": "תשלום בכרטיס, כרטיס המסתיים ב־4821: -$84.20", "protection": { "status": "ok", … }, … },
    { "text": "ריבית שזוכתה: +$3.15 (ריבית שנתית 4.5%)", "protection": { "status": "ok", … }, … },
    { "text": "עמלת משיכת יתר בוטלה ב־4 במרץ 2026", "protection": { "status": "ok", … }, … },
    { "text": "העברה ל־IBAN GB29 NWBK 6016 1331 9268 19", "protection": { "status": "ok", … }, … }
  ],
  "usage": { "characters": 153 }
}
```

### Pitfalls

- **Direction words.** A translation that turns a credit into a debit, or "you owe" into "you are owed", is rejected and falls back. Treat fallback lines as untranslated.
- **English dates by default.** English sources default to `MDY`. A statement from an Israeli bank needs `DMY`.
- **Regulatory text.** Translation does not change which version is binding. Keep the original available.

## Legal & Contracts

Contracts, terms of service, privacy policies and formal notices, where "shall" and "may" are not the same word and Section 4.2 must still point to Section 4.2.

### What to Use

| Need | Use |
| --- | --- |
| Legal protection and register | `domain: "legal"`, described in [Domains](https://hc.itsbaba.com/docs#domains). |
| Party names | `protected_terms`, or `redact_terms` for private individuals. |
| Fixed renderings of defined terms | `glossary`, for example `"Effective Date": "המועד הקובע"`. |
| Long documents | One clause per item in `/v1/translate/batch`, at `quality: "smartest"`. |

### Example

```http
POST /v1/translate
{
  "text": "The Supplier shall not assign this Agreement without the prior written consent of Northwind Ltd. (the \"Customer\"). The Customer may terminate this Agreement on 30 days' notice.",
  "source_lang": "en",
  "target_lang": "he",
  "domain": "legal",
  "protected_terms": ["Northwind Ltd."],
  "quality": "smartest"
}

{
  "translation": {
    "text": "הספק לא יסב הסכם זה ללא הסכמה מראש ובכתב של Northwind Ltd. (להלן: ״הלקוח״). הלקוח רשאי לסיים הסכם זה בהודעה מוקדמת של 30 יום.",
    "dir": "rtl",
    "protection": {
      "status": "ok",
      "spans": [
        { "type": "term", "value": "Northwind Ltd." },
        { "type": "defined_term", "value": "Customer", "render": "הלקוח" },
        { "type": "number", "value": "30" }
      ],
      "issues": [],
      …
    }
  }
}
```

### Pitfalls

- **Defined terms are translated.** "the Customer" becomes (להלן: ״הלקוח״) once and הלקוח after that. Pin a specific rendering with `glossary`; put a party's legal name in `protected_terms` to keep it as written.
- **Modality.** If "shall not" comes back as "may not", or "may" as "shall", the sentence falls back. Review fallback clauses by hand.
- **Size.** A single request carries up to 20,000 characters. Split a long contract by clause, which also keeps retries small.
- **Binding text.** A translation is a reading aid. State which language governs, and keep the original with it.

## Education & Publishing

Language-learning apps, children's books, readers and audio, where vowel points, transliteration and the learner's gender matter as much as the translation.

### What to Use

| Need | Use |
| --- | --- |
| Vocalized text for readers and speech | `/v1/nikud`, checked so no letter changes. |
| A reading in Latin letters | `transliterate: true` on `/v1/translate`, or `/v1/transliterate`. |
| Addressing the learner | `listener_gender` on protected translation (`סיימת`, `ты закончила`). |
| Search across vocalized text | `/v1/strip-nikud` to build search keys. |
| Course interface strings | The [App Localization](https://hc.itsbaba.com/docs#solution-localization) setup. |

### Example

```http
POST /v1/nikud
{ "text": "הילדים קוראים ספר בספרייה" }

{ "text": "הילדים קוראים ספר בספרייה", "nikud": "הַיְלָדִים קוֹרְאִים סֵפֶר בַּסִּפְרִיָּה", "verified": true }

POST /v1/translate
{ "text": "The children are reading a book in the library.", "target_lang": "he", "transliterate": true }

→ "text": "הילדים קוראים ספר בספרייה.", "transliteration": "Hayeladim kor'im sefer basifriya."
```

### Pitfalls

- **Unverified nikud.** When `verified` is false, `nikud` is your text unchanged. Show or speak the plain text.
- **Transliteration scheme.** The scheme is a general reading aid, not an academic standard. Keep that in mind for citations.
- **Mixed search.** Index both the plain and the vocalized form, or strip nikud from queries and documents alike.

## Healthcare

Patient portals, care-team tools and clinical assistants that work in English and speak to patients in Hebrew. Short messages use `domain: "clinical"` on `/v1/translate`; streamed answers, record search and verification use the [Clinical API](https://hc.itsbaba.com/docs#medical).

### What to Use

| Need | Use |
| --- | --- |
| A short message or instruction | `/v1/translate` with `domain: "clinical"`, `audience` and `patient_gender`. |
| An answer your model is still writing | Streaming: [WebSocket /v1/medical/stream](https://hc.itsbaba.com/docs#medical-stream) or [Server-Sent Events](https://hc.itsbaba.com/docs#medical-sse). |
| A Hebrew question against English records | [/v1/medical/query](https://hc.itsbaba.com/docs#medical-query). |
| Checking Hebrew written elsewhere | [/v1/medical/verify](https://hc.itsbaba.com/docs#medical-verify). |
| The patient's medications and names | `protected_terms` from your record search; `redact_terms` for names. |

### Example

```http
POST /v1/translate
{
  "text": "Take Eliquis 5 mg twice a day. Do not take ibuprofen. Your next INR check is on 03/04/2026.",
  "target_lang": "he",
  "domain": "clinical",
  "audience": "patient",
  "listener_gender": "female",
  "protected_terms": ["Eliquis 5 mg"]
}

{
  "translation": {
    "text": "יש ליטול Eliquis 5 mg פעמיים ביום. אין ליטול איבופרופן. בדיקת ה־INR הבאה שלך תתקיים ב־4 במרץ 2026.",
    "dir": "rtl",
    "protection": {
      "status": "ok",
      "spans": [
        { "type": "term", "value": "Eliquis 5 mg" },
        { "type": "abbreviation", "value": "INR" },
        { "type": "date", "value": "03/04/2026", "render": "4 במרץ 2026", "ambiguous_date": true }
      ],
      …
    }
  }
}
```

### Pitfalls

- **Server only.** `/v1/medical` refuses browser requests, and needs a key with the `medical` scope. Use synthetic data in the playground.
- **US record dates.** Clinical dates default to `MDY`; set `date_order: "DMY"` for Israeli records.
- **Fallback sentences.** Show a `fallback` sentence in English and keep the English original available.

## Guide: Localizing an App or Site

Send interface strings to `/v1/translate/batch` with `protect: true`. Variables such as `{count}`, `{{name}}` and `%s` stay in place, and a `glossary` fixes the words your product always uses ("Checkout" → "לתשלום"). Set `listener_gender` when you know the user's gender; without it, Hebrew labels and buttons use the neutral infinitive (להציג עוד). Translate once at build time and ship the results with your app.

## Guide: Mixed-Direction Display

A Hebrew line with prices, model numbers, dates or ranges needs more than `dir="rtl"`: the Unicode algorithm alone splits "10–20%" around the dash and mirrors "<5". Pass each display string through `/v1/wrap` with `base: "rtl"` and pick the format for the surface:

| Surface | Format |
| --- | --- |
| Web, React, webviews | `html` |
| iOS, Android 7+, desktop apps | `isolate` |
| Older Android, embedded and small displays, any renderer you cannot test | `marks` |

`/v1/wrap` is deterministic and fast enough to call per line at render time, or you can wrap once when the string is created and store the result.

## Guide: Assistants and Chat

For an assistant that answers in Hebrew or Russian, detect the user's language with `/v1/detect`, generate the answer in your usual language, and translate it with protected translation at `quality: "fast"`. Set `speaker_gender` for the assistant's voice and `listener_gender` for the user, and pass the names, products and amounts from your data as `protected_terms`. When a sentence comes back with `status: "fallback"`, show it in the source language or ask the user to rephrase; never retranslate it without the checks.

## Guide: Voice Output

Unvocalized Hebrew is ambiguous for speech engines. Send the text you will speak to `/v1/nikud` and pass the vocalized result to your text-to-speech engine, while the screen keeps the plain text (or use `/v1/strip-nikud` to get it back). English terms and numbers pass through unchanged. If `verified` is false, speak the plain text.

## Guide: Regulated Content

Finance, insurance, legal and health content share one rule: an amount, a date, a code or a negation must never change in translation. Protected translation enforces that for every request, and `redact_terms` keeps personal names out of the model entirely. Pick the [domain](https://hc.itsbaba.com/docs#domains) that matches the text: `finance` for statements and notices, `legal` for contracts and policies, and `clinical` for health content, or the [Clinical API](https://hc.itsbaba.com/docs#medical) for streaming, record search and verification. The [solution guides](https://hc.itsbaba.com/docs#solutions) walk through each. For processing agreements, subprocessors and regions, contact us.

## Clinical API

The `/v1/medical` endpoints serve health products that work in English and speak to people in Hebrew: patient portals, care-team tools, clinical assistants and record viewers. Records, search and your own model stay in English. HebrewCore turns a Hebrew question into an English query, then turns the English answer into Hebrew as it streams, one verified sentence at a time.

Real patient data goes only from your server, with an API key. The [playground](https://hc.itsbaba.com/docs#playground) runs in the browser, so use synthetic data only there.

```text
Hebrew question ──► POST /v1/medical/query ──► English query ──► your record search + model
                                                                          │ English answer, streamed
Hebrew answer ◄── verified sentences ◄── WebSocket /v1/medical/stream ◄──┘
```

Every sentence goes through the same steps before it is returned:

| Step | What happens |
| --- | --- |
| Protect | Drug names (US generics and brands, plus unknown drugs by their name stem), doses and concentrations, lab values, units, ICD-10 codes, clinical abbreviations, identifiers and every number are replaced with placeholders the model cannot change. Your `protected_terms`, `redact_terms` and [account terms](https://hc.itsbaba.com/docs#terms) come first. |
| Translate | The model translates the words around the placeholders into Israeli medical Hebrew for a clinician or a patient. |
| Check | Every placeholder must appear exactly once, every number in the English must appear in the Hebrew and no number may be invented, negations and left/right must survive, and the length must be plausible. |
| Review | An independent model checks every sentence for meaning changes: certainty, timing, dosing wording, who is being described, omissions and additions. |
| Retry or fall back | A rejected sentence is retried once with a stronger model, told what was wrong. If it still fails, the English sentence is returned with `status: "fallback"`. Unverified Hebrew is never returned. |
| Restore | The original values are put back, wrapped in Unicode isolates so `5 mg` never renders as `mg 5`. Dates are rewritten unambiguously (`03/04/2026` → `4 במרץ 2026`). |

### Segment Status

| Status | Meaning |
| --- | --- |
| `ok` | Translated and verified on the first attempt. |
| `retried` | The first attempt was rejected; the retry passed every check. |
| `fallback` | No translation passed. `text` is the English source; `issues` says why. Show it as English, or ask the user to rephrase. |
| `passthrough` | Structure or values only (a blank line, a rule, a date on its own). No model was needed. |

## Access & Data Handling

> The Clinical API is enabled per account under a data processing agreement (and a BAA for US covered entities). Keys need the `medical` scope; other keys get `403 scope_required`.

- **Server to server only.** A request carrying a browser `Origin` header is refused with `403 server_only`. Never put a medical key in a browser or app.
- **Nothing is stored.** Only character counts are kept for billing. Responses carry `Cache-Control: no-store` and `X-Content-Stored: false`.
- **Names and identifiers never reach the model.** Values passed in `redact_terms`, and record numbers, phone numbers, SSNs and emails found in the text, are sent to the model as blank placeholders and put back afterwards. They are also left out of the `spans` list in responses.
- **Dedicated model access.** Medical traffic goes directly to the model provider under contract, with storage turned off. It never passes through a model reseller or a logging gateway.

## POST /v1/medical/translate

`POST /v1/medical/translate`

Translate a complete English text. Sentences are translated in parallel and returned in order.

| Parameter | Type | Description |
| --- | --- | --- |
| `text` *required* | string | 1–20,000 characters of English. Markdown lists, headings and tables keep their structure. |
| `audience` | enum | `clinician` (default) keeps shorthand such as BID and PO. `patient` writes it as plain Hebrew. |
| `reader_gender` | enum | `male` · `female`. How to address "you". Omit when unknown. |
| `patient_gender` | enum | `male` · `female`. The patient in third-person references. Inferred from he/she when omitted. |
| `protected_terms` | string[] | Kept verbatim, e.g. the medication and problem lists your record search returned. Up to 500. |
| `redact_terms` | string[] | Kept verbatim and never shown to the model: patient and staff names. Up to 200. |
| `glossary` | object | English term → required Hebrew rendering, e.g. `{"hypertension": "יתר לחץ דם"}`. Up to 500. |
| `date_order` | enum | How to read ambiguous numeric dates: `MDY` (default, US records) or `DMY`. |
| `date_style` | enum | `hebrew` (default, "4 במרץ 2026") · `iso` ("2026-03-04") · `keep` (unambiguous dates only; an ambiguous one is still rewritten). A two-digit year is kept as written. |
| `bidi` | enum | `isolate` (default) wraps English values in Unicode isolates · `none`. |

```bash
curl https://hc.itsbaba.com/v1/medical/translate \
  -H "Authorization: Bearer hc_live_YOUR_MEDICAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "You are taking Eliquis 5 mg twice a day. Your dose was changed on 03/04/2026.",
    "audience": "patient",
    "reader_gender": "female",
    "protected_terms": ["Eliquis 5 mg", "atrial fibrillation"]
  }'
```

### Response

```json
{
  "id": "med_…",
  "text": "את נוטלת Eliquis 5 mg פעמיים ביום. המינון שלך שונה ב־4 במרץ 2026.",
  "segments": [
    {
      "index": 0, "prefix": "", "suffix": " ",
      "source": "You are taking Eliquis 5 mg twice a day.",
      "text": "את נוטלת Eliquis 5 mg פעמיים ביום.",
      "status": "ok", "issues": [],
      "spans": [ { "type": "term", "value": "Eliquis 5 mg" } ]
    },
    {
      "index": 1, "prefix": "", "suffix": "",
      "source": "Your dose was changed on 03/04/2026.",
      "text": "המינון שלך שונה ב־4 במרץ 2026.",
      "status": "ok", "issues": [],
      "spans": [ { "type": "date", "value": "03/04/2026", "render": "4 במרץ 2026", "ambiguous_date": true } ]
    }
  ],
  "stats": { "segments": 2, "ok": 2, "retried": 0, "fallback": 0, "passthrough": 0 },
  "usage": { "characters": 77 }
}
```

## WebSocket /v1/medical/stream

`GET /v1/medical/stream` (WebSocket upgrade)

For an answer your model is still generating. Send the English as it arrives; each Hebrew sentence comes back as soon as it is verified, typically about 2–3 seconds after the English sentence completes. Authenticate with the `Authorization` header on the upgrade request.

| Message | Direction | Meaning |
| --- | --- | --- |
| `{"type":"start", …options}` | → | First message. Takes every option of `/v1/medical/translate` except `text`. |
| `{"type":"delta","text":"…"}` | → | The next piece of English. Any size, in order. Up to 100,000 characters per session. |
| `{"type":"end"}` | → | No more English. The rest is flushed. |
| `{"type":"ready"}` | ← | Options accepted. |
| `{"type":"segment", …}` | ← | One sentence, the same shape as a `segments[]` entry, strictly in order. |
| `{"type":"done","stats","usage"}` | ← | Everything delivered. The socket then closes with code 1000. |
| `{"type":"error","error":{type,message}}` | ← | The session stops and the socket closes. `quota_exceeded` closes with 1008. |

```js
// Server-side only. Pipes your model's English answer through HebrewCore
// and shows each verified Hebrew sentence as soon as it is ready.
import OpenAI from "openai";

const ws = new WebSocket("wss://hc.itsbaba.com/v1/medical/stream", {
  headers: { Authorization: `Bearer ${process.env.HEBREWCORE_MEDICAL_KEY}` },
});
await new Promise((r) => ws.addEventListener("open", r));

ws.addEventListener("message", (e) => {
  const msg = JSON.parse(e.data);
  if (msg.type === "segment") sendToUser(msg.prefix + msg.text + msg.suffix, msg.status);
  if (msg.type === "error") handleError(msg.error);
  if (msg.type === "done") finish(msg.stats);
});

ws.send(JSON.stringify({
  type: "start",
  audience: "patient",
  reader_gender: "male",
  protected_terms: patient.medications,   // from your record search
  redact_terms: [patient.fullName],
}));

const stream = await new OpenAI().chat.completions.create({ model, messages, stream: true });
for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) ws.send(JSON.stringify({ type: "delta", text: delta }));
}
ws.send(JSON.stringify({ type: "end" }));
```

Characters are charged per sentence as it starts, so a session that hits the quota stops exactly there. A session idle for 60 seconds is closed.

## POST /v1/medical/translate/stream

`POST /v1/medical/translate/stream`

Same body as `/v1/medical/translate`, answered as Server-Sent Events so the first sentence can be shown before the last is done. Events: `segment`, then `done` or `error`.

## POST /v1/medical/query

`POST /v1/medical/query`

Turn a Hebrew question into an English query for your record search. English terms, numbers and dates in the question are kept exactly (Hebrew day-first dates become ISO dates). Hebrew spellings of English drug names are mapped back to English, preferring the patient's own terms from `known_terms`. `text` up to 2,000 characters.

```http
POST /v1/medical/query
{ "text": "האם המטופלת עדיין לוקחת מטפורמין?", "known_terms": ["metformin", "lisinopril"] }

{
  "query": "Is the patient still taking metformin?",
  "terms": [ { "hebrew": "מטפורמין", "english": "metformin", "source": "known_terms" } ],
  "usage": { "characters": 33 }
}
```

## POST /v1/medical/verify

`POST /v1/medical/verify`

Check Hebrew that was produced some other way, for example by your own model answering in Hebrew, against its English source. Every protected value must appear verbatim, dates must be unambiguous, no number may be added, and negation and laterality must survive. Set `verification: "strict"` to add the independent review; names in `redact_terms` and identifiers are replaced before the reviewer sees the text.

```http
POST /v1/medical/verify
{
  "source": "Metformin 500 mg BID since 03/04/2026.",
  "translation": "Metformin 50 mg BID מאז 03/04/2026."
}

{
  "pass": false,
  "issues": [
    { "code": "term_missing", "severity": "error", "detail": "\"500 mg\" (dose) is missing or altered." },
    { "code": "date_missing", "severity": "error", "detail": "The date \"03/04/2026\" is missing or kept in an order a Hebrew reader will misread." },
    { "code": "number_added", "severity": "error", "detail": "The number 50 does not appear in the source." }
  ],
  "usage": { "characters": 72 }
}
```

> Translation is an aid, not a clinical record. Keep the English original available to the user, and treat any sentence with `status: "fallback"` as untranslated.

> Looking for the full machine-readable contract? The OpenAPI 3.1 spec is at [`/openapi.json`](https://hc.itsbaba.com/openapi.json), rendered interactively at [/reference](https://hc.itsbaba.com/reference).
