Developer guide
SDK guide
Three packages, one model: you create a client once with your credentials, then start a session for what you want to do — fill a form by voice, or fill it from text. Every session reports the same state; React gives it to you as plain values, Angular as signals, JavaScript through subscribe(). The options are identical everywhere — only the function that takes them differs: useSpeechToForm / injectSpeechToForm / client.speechToForm().
1. Create the client
Development: your workspace's API key plus an account that identifies the end user (usage is tracked per account). Production: a token your server signs per user — a string, or a function that fetches a fresh one; the SDK asks for it on every session start. Details in Authentication and accounts. baseUrl defaults to the production Speechineer API.
npm add @speechineer/react// main.tsx — once. Development: your workspace's API key + the end user's account.
// Production: a token your server signs per user (see Authentication).
import { SpeechineerProvider } from "@speechineer/react";
<SpeechineerProvider apiKey={import.meta.env.VITE_SPEECHINEER_KEY} account={{ key: currentUser.id }}>
<App />
</SpeechineerProvider>2. Fill a form by voice
Name the form you configured in Speechineer (form.source: "workspace" — its fields, prompts and models come from your workspace, so you can change them without a release) and render from the state: isListening for the button, values for the fields, error when something needs attention.
import { useSpeechToForm } from "@speechineer/react";
function TalkToForm() {
const { start, stop, isListening, values, error } = useSpeechToForm({
form: { source: "workspace", key: "patient-intake", version: "1", language: "en" },
});
return (
<>
<button type="button" onClick={isListening ? stop : () => void start()}>
{isListening ? "Stop" : "Talk"}
</button>
<input value={String(values.patientName ?? "")} readOnly />
{error && <p role="alert">{error.message}</p>}
</>
);
}start() asks for microphone permission the first time, connects, and begins listening; stop() pauses (values still being recognized arrive); end() finishes the session and releases everything. Calling start() again after stop() continues the same session.
Inline forms — fields in your code
Prefer to keep the form definition in your repository? Use form.source: "inline" and declare the fields with FormField. The prompt is the instruction Speechineer follows for that field, so be specific about the value you want. Speechineer records the inline form under your key / version in your workspace, so usage is attributed like any other form.
import { FormField } from "@speechineer/react"; // also exported by @speechineer/angular and @speechineer/js
const form = {
source: "inline",
key: "patient-intake", // your own stable key — Speechineer records the form under it
version: "1",
language: "en",
fields: [
FormField.text("patientName", "Extract the patient full name"),
FormField.integer("age", "Extract the age in years"),
FormField.select("species", "Extract the species", ["Canine", "Feline", "Equine"]),
],
prompts: { extraction: "Values are for a veterinary intake form." }, // optional
models: { transcription: "fast-de" }, // optional — keys from your workspace
} as const;
const { start, stop, values } = useSpeechToForm({ form, spokenLanguage: "de" });Field types: text, textarea, email, phone, url, integer, float, checkbox, date, time, datetime, select (options), multiselect (options), slider (range). prompts (transcription, extraction) and models (the model configurations you named in your workspace) are optional and only apply to inline forms. spokenLanguage is a hint for recognition; omit it to detect automatically.
Show the transcript
Add transcript: true and the spoken text streams into transcript (and onTranscript) while the fields fill in — useful when the user should see what was heard. Fixed for the session: change it by creating a new one.
const { start, stop, values, transcript } = useSpeechToForm({
form,
transcript: true, // also stream the spoken text
onTranscript: (text) => console.log(text), // optional — `transcript` is state too
});Fill a form from text
No microphone: useTextToForm / injectTextToForm / client.textToForm() take the same form and give you extract(text). It opens the session on first use; every result is merged into values.
const { extract, values, isExtracting } = useTextToForm({ form });
// later, for example on a button:
const extracted = await extract("Patient Jane Doe, born 1990-03-28, feline.");
// `extracted` holds this call's values; `values` holds the merged stateSession state
| Field | What it tells you |
|---|---|
| values | The latest recognized value of every field, keyed by field id — starts with initialValues if you pass them. |
| transcript | The spoken text so far (with transcript: true). |
| isListening | The microphone is on and audio is being sent — the button state. |
| isConnecting | The session or one of its connections is being established. |
| isEnding | end() is finishing the session, or the microphone is winding down after stop(). |
| error | The last SpeechineerError, or null; cleared when the next start() succeeds. |
| sessionId | The id of the running session, or null. |
| status | The lifecycle: idle · starting · active · recovering · ending · failed. |
| connections | The status of each connection (session, audio, results, transcript): closed · connecting · open · closing. |
Resuming a partly filled form: pass initialValues (keyed by field id) — they appear in values immediately and Speechineer continues from them. Pass account on the session when it differs from the client's default.
Callbacks
All optional — everything they report is also in the state. Use them for imperative integrations (a form library, logging, analytics).
useSpeechToForm({
form,
onFieldValue: (fieldId, value) => setValue(fieldId, value), // push into react-hook-form, Formik, …
onTranscript: (text) => setTranscript(text),
onSessionStart: (sessionId) => log("session", sessionId),
onStateChange: (state) => log("state", state.status),
onEvent: (event) => log(event.type, event.level, event.payload),
onError: (error) => toast(error.code, error.message, error.recoverable),
});Errors are one type, SpeechineerError: branch on code (stable), show message, and offer a retry when recoverable is true. The codes are listed under Errors. Full option and return tables per framework are in the API reference.