Skip to main content
Version: 0.0.16

Connections

Connection Types​

The SDK supports different connection modes based on the provider:

API Key Connection​

{
apiKey: string;
config?: BaseConfig;
}

Sofya Compliance Provider Connection​

{
provider: "sofya_compliance";
endpoint: string;
config: SofyaComplianceConfig;
}

Sofya As Service Provider Connection​

{
provider: "sofya_as_service";
endpoint: string;
config: SofyaSpeechConfig;
}

Configuration Types​

BaseConfig​

interface BaseConfig {
language: string;
external_id?: string;
record?: boolean;
}
FieldTypeDescription
external_idstring (optional)Identifier of the consultation in your application. Sent to the server as the x-external-id query param on every connection — including reconnections — and used to group all recordings belonging to the same consultation. Must be opaque: a UUID, hash, or internal id — never a CPF, name, readable medical record number, or email. To be used literally in the recording's storage path it must match ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ (starts with a letter or digit, up to 64 characters, no :, /, spaces or accents); outside that pattern the server stores the recording under a hash and keeps the original value only in the metadata. Maximum 512 characters. Use the same value on every reconnection for a given consultation.
recordboolean (optional)Requests (true) or refuses (false) server-side recording of this session. When omitted, the SDK sends nothing and the environment's default decides. true only results in a recording if the environment allows it — otherwise the session proceeds normally. Recording never changes the transcription itself.
const transcriber = new SofyaTranscriber({
provider: "sofya_as_service",
endpoint: "<wss-url>",
config: {
language: "pt-BR",
external_id: "<consultation-id>",
record: true,
},
});
Compatibility

external_id and record are additive and optional. Applications that don't set them keep working exactly as before, including against older servers.

SofyaComplianceConfig​

interface SofyaComplianceConfig extends BaseConfig {
token: string;
compartmentId: string;
region: string;
}

SofyaSpeechConfig​

interface SofyaSpeechConfig extends BaseConfig {
auth?: DirectModeAuth;
}

Authentication in Direct Mode (auth)​

Direct connections ({ provider, endpoint, config }) can send the STT API key through the optional config.auth field. It is available on the configs of the direct Whisper providers (sofya_as_service, sofya_whisper_flow, stt_wvad); the API key connection is unchanged, because it already authenticates through the Sofya API.

type DirectModeAuth =
| { type: "none" }
| {
type: "api_key";
key: string;
transport?: "subprotocol" | "query";
}
| { type: "jwt"; token: string };
FieldTypeDescription
type"none" | "api_key" | "jwt""none" is the default when auth is omitted and sends no credentials. "api_key" sends the STT API key. "jwt" sends a JWT instead (see JWT).
keystringThe STT API key. Required when type is "api_key". The SDK never transforms it.
transport"subprotocol" | "query" (optional)How the key reaches the server. Defaults to "subprotocol". Browsers cannot set headers on a WebSocket handshake, so these are the only two options.
tokenstringThe raw JWT. Required when type is "jwt". Without Bearer — the SDK adds it.

transport: "subprotocol" (default)​

The key travels as an extra Sec-WebSocket-Protocol token, x-api-key.<key>. The server strips that token before the application sees it and echoes back the first requested subprotocol, so the SDK always keeps your own protocols in front and appends the key token last.

const transcriber = new SofyaTranscriber({
provider: "sofya_as_service",
endpoint: "<wss-url>",
config: {
language: "pt-BR",
auth: { type: "api_key", key: "<stt-api-key>" },
},
});
config.protocolsSubprotocols sent on the handshake
omitted["sofya-stt.v1", "x-api-key.<key>"]
"bearer.jwt"["bearer.jwt", "x-api-key.<key>"]
["bearer.jwt", "sofya-stt.v1"]["bearer.jwt", "sofya-stt.v1", "x-api-key.<key>"]
  • The server rejects a handshake whose only subprotocol is the key token (subprotocol_companion_required), so the SDK adds the sofya-stt.v1 companion token when you configure no protocol.
  • RFC 6455 subprotocol tokens accept only letters, digits and !#$%&'*+-.^_`|~ — =, /, ,, spaces and quotes are not allowed. With a key outside that set the SDK throws SofyaAuthError before connecting; issue a token-safe key or use the query transport.

transport: "query"​

The key is appended to the realtime URL as the x-api-key query parameter and config.protocols are forwarded untouched.

const transcriber = new SofyaTranscriber({
provider: "sofya_as_service",
endpoint: "<wss-url>",
config: {
language: "pt-BR",
auth: {
type: "api_key",
key: "<stt-api-key>",
transport: "query",
},
},
});
Keys in URLs

URLs are recorded by proxies, gateways, access logs and browser history. Prefer subprotocol and use query only when the key cannot be an RFC 6455 token.

  • Reconnections reuse the same authentication — the URL and the subprotocol list are rebuilt identically on every attempt.
  • The key is also sent as the x-api-key header on the HTTP calls the SDK makes (batch reprocess and audit ingestion), unless that header is already configured.
  • The SDK never logs the key: it appears as [redacted] in debug output.
  • When the server rejects the key it denies the handshake with HTTP 401 or closes with code 4401. On 4401 the SDK emits error with a SofyaAuthError (code AUTH_REJECTED) and stops reconnecting instead of retrying the same key.
Compatibility

auth is additive and optional. Omitting it (or using { type: "none" }) keeps the previous behavior, including the configured protocols and the URL.

type: "jwt"​

Sends a JWT instead of the API key. The two strategies are exclusive: a session authenticates with one of them, and every request the SDK makes follows it.

const transcriber = new SofyaTranscriber({
provider: "sofya_as_service",
endpoint: "<wss-url>",
config: {
language: "pt-BR",
auth: { type: "jwt", token: "<jwt>" }, // "eyJ...", not "Bearer eyJ..."
},
});
Pass the raw JWT

Do not add Bearer to the token: the SDK adds the prefix to the HTTP requests. A token that starts with Bearer makes the SDK throw SofyaAuthError with the code INVALID_JWT before connecting; the prefix is never removed silently.

Requestapi_keyjwt
WebSocketx-api-key.<key> subprotocol (last) or x-api-key querythe JWT as the first subprotocol, before config.protocols, so the server echoes it
Batch, batch reprocess, audit ingestionx-api-key headerAuthorization: Bearer <token>
Final uploadnonenone
  • Realtime sessions send the JWT as a subprotocol, so it must be an RFC 6455 token. A standard JWT (base64url, no padding) always is; anything with =, /, ,, spaces or quotes throws SofyaAuthError (INVALID_JWT_CHARACTERS) before connecting. Batch sessions send it only as a header and accept any character.
  • Do not also put the JWT in config.protocols, or it is sent twice.
  • An Authorization header set in config.headers wins over the JWT.
  • The Sofya STT does not validate JWTs. Use jwt with STTs that have authentication off or sit behind a gateway that validates the token; an STT that requires an API key rejects the connection. Audit ingestion requires x-api-key, so with jwt alone it is skipped with the missing_api_key warning.
  • The JWT never appears in debug output ([redacted]).
Deprecated config.token

In direct mode, config.token is deprecated and will be removed in 1.0.0; use auth: { type: "jwt", token }. Until then it still becomes Authorization: Bearer <token>, the SDK logs a deprecation warning, and auth.token wins when both are set.

Connection Flow​

API Key Connection Flow​

  1. The SDK authenticates with the Sofya API using the provided API key.
  2. The API returns a list of available providers and their configurations.
  3. The SDK attempts to connect to each provider in order until a successful connection is established.
  4. Once connected, the SDK emits a 'ready' event.

Provider-Specific Connection Flow​

  1. The SDK attempts to connect directly to the specified provider using the provided endpoint and configuration.
  2. Once connected, the SDK emits a 'ready' event.