Skip to content

Assistants

Choosing a voice, model, and transcriber

Browse the three catalogues an assistant references (voices, language models, and transcribers) and pick the IDs you configure it with.

Before an assistant can take a call it needs three IDs: a voice to speak with, a language model to reason with, and a transcriber to hear with. All three come from read-only catalogues that OnCore maintains for you: browse a catalogue, pick a row, keep its id.

MethodPathPurpose
GET/voicesList the voice catalogue
GET/voices/{id}Get one voice
GET/modelsList the language-model catalogue
GET/models/{id}Get one model
GET/transcribersList the transcriber catalogue
GET/transcribers/{id}Get one transcriber

For the endpoint-by-endpoint schemas, see the Voices, Models & Transcribers reference.

How the catalogues work#

The three catalogues behave identically, so learning one teaches you all three:

  • They are read-only. Only GET is exposed; you choose from what OnCore offers rather than registering your own entries.
  • Every list is paginated and reports a total, so you can tell when you have seen everything.
  • Every response uses the standard envelope: the payload sits in data, alongside success and metadata. See Conventions.
  • Store the id, never the display name. name is a label that can repeat (the same voice can appear more than once under different underlying models), while id is the stable reference. Versioning explains why these catalogues are expected to grow.

All three list endpoints take the same two query parameters:

Query paramTypeRequiredDescription
limitnumberNoPage size. Default 50, maximum 500.
offsetnumberNoItems to skip. Default 0.

Pick a voice#

GET /voices returns the catalogue; GET /voices/{id} returns a single entry once you know its ID.

bash
curl "https://core-api.heysadie.ai/voices?limit=50" \
  -H "Authorization: ApiKey YOUR_API_KEY"

The list arrives in data.voices, with the catalogue size in data.total:

GET /voices response
{
  "success": true,
  "data": {
    "voices": [
      {
        "id": "0195f1e2-5555-7000-8000-000000000000",
        "name": "Example Voice",
        "provider": "example-provider"
      }
    ],
    "total": 42
  },
  "metadata": {
    "timestamp": "2026-07-30T12:00:00.000Z",
    "version": "1.0",
    "path": "/voices"
  }
}

Each entry in data.voices carries these fields:

FieldTypeDescription
idstringAlways present. The UUID you send as voiceId on an assistant.
namestringAlways present. The voice's display label.
providerstringAlways present. Which provider supplies the voice.
bodyn/aAlways present. The spec declares no type for this field.
tagsn/aOptional. The spec declares no type for this field.
languagen/aOptional. The spec declares no type for this field.

tags and language are string arrays; body is provider-shaped

tags (on voices, models and transcribers) and language (on voices) are each an array of strings, optional and nullable: expect null as readily as an empty array, and guard for it.

body on a voice is genuinely untyped: it carries the provider's own payload for that voice, so its shape varies by provider and no single schema describes it. Read it if you need provider-specific detail, but do not write a type against it.

What each provider accepts in body, with the range for every setting, is documented under Providers. Read the page for your provider before changing a value: providers disagree on how they treat a setting they dislike, and on some of them a value outside its range ends the call rather than being ignored.

GET /voices/{id} returns the same fields, but as a bare object in data rather than inside a voices array:

Terminal
curl https://core-api.heysadie.ai/voices/0195f1e2-5555-7000-8000-000000000000 \
  -H "Authorization: ApiKey YOUR_API_KEY"
GET /voices/{id} response (data only)
{
  "id": "0195f1e2-5555-7000-8000-000000000000",
  "name": "Example Voice",
  "provider": "example-provider"
}

If your callers do not all speak the same language, read Multi-language calls before you settle on a voice. Some voices in the catalogue speak one language and others speak several, and that choice decides who your assistant can serve.

Pick a language model#

GET /models lists the language models an assistant can reason with; GET /models/{id} returns one of them.

bash
curl "https://core-api.heysadie.ai/models?limit=50" \
  -H "Authorization: ApiKey YOUR_API_KEY"

The list arrives in data.models, with the catalogue size in data.total:

GET /models response (data only)
{
  "models": [
    {
      "id": "0195f1e2-6666-7000-8000-000000000000",
      "name": "Example Model",
      "model": "example-model-v1",
      "provider": "example-provider"
    }
  ],
  "total": 12
}
FieldTypeDescription
idstringAlways present. The UUID you send as modelId on an assistant.
namestringAlways present.
modelstringAlways present.
providerstringAlways present. Which provider serves the model.
tagsn/aOptional. The spec declares no type for this field.

name versus model

name is the human-readable label to show in a picker. model is the provider model identifier used by the voice runtime. Store the resource id as the assistant's modelId; display name with provider, and use model only when you need to inspect the underlying provider configuration.

GET /models/{id} returns the same fields as a bare object in data:

Terminal
curl https://core-api.heysadie.ai/models/0195f1e2-6666-7000-8000-000000000000 \
  -H "Authorization: ApiKey YOUR_API_KEY"

Pick a transcriber#

The transcriber is the speech-to-text engine that turns what the caller says into text for the model. GET /transcribers lists the catalogue; GET /transcribers/{id} returns one entry.

bash
curl "https://core-api.heysadie.ai/transcribers?limit=50" \
  -H "Authorization: ApiKey YOUR_API_KEY"

The list arrives in data.transcribers, with the catalogue size in data.total:

GET /transcribers response (data only)
{
  "transcribers": [
    {
      "id": "0195f1e2-7777-7000-8000-000000000000",
      "name": "Example Transcriber",
      "provider": "example-provider"
    }
  ],
  "total": 8
}
FieldTypeDescription
idstringAlways present. The UUID you send as transcriberId on an assistant.
namestringAlways present. The transcriber's display label.
providerstringAlways present. Which provider supplies the transcriber.
tagsn/aOptional. The spec declares no type for this field.

A transcriber entry has no language field, so this page does not state which languages any given transcriber covers.

Terminal
curl https://core-api.heysadie.ai/transcribers/0195f1e2-7777-7000-8000-000000000000 \
  -H "Authorization: ApiKey YOUR_API_KEY"

Use the three IDs#

Once you have one id from each catalogue, pass them to the assistant as voiceId, modelId, and transcriberId: on POST /assistants when you create it, or on PATCH /assistants/{id} to swap one later.

bash
curl -X PATCH https://core-api.heysadie.ai/assistants/0195f1e2-2222-7000-8000-000000000000 \
  -H "Authorization: ApiKey YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "voiceId": "0195f1e2-5555-7000-8000-000000000000",
    "modelId": "0195f1e2-6666-7000-8000-000000000000",
    "transcriberId": "0195f1e2-7777-7000-8000-000000000000"
  }'

Because the catalogues grow, resolve these IDs once and store them rather than looking them up on every call. Re-check them when you want a newly added voice or model. Assistants covers the rest of the configuration these three IDs sit alongside.

When a lookup fails#

All six endpoints return the standard error envelope, made up of success: false plus an error object with a machine-readable code, a human-readable message, and, for validation failures, a details array of { field, message } entries:

Error response
{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Voice not found"
  },
  "metadata": {
    "timestamp": "2026-07-30T12:00:00.000Z",
    "version": "1.0",
    "path": "/voices/0195f1e2-5555-7000-8000-000000000000"
  }
}

Each of the six can answer 400, 401, 403, 404, or 500. Branch on error.code, never on error.message. Errors lists every code and what it means.

Noisy callers#

Every call runs background noise reduction on the caller's audio before it reaches the transcriber. It is always on and there is nothing to configure: a caller in a car, a cafe or a warehouse is already handled, and you do not need to pick a transcriber for robustness to noise.

What it does not remove is a second person talking nearby, which the transcriber may still pick up as caller speech. If an assistant reacts to something the caller did not say, that is usually the cause rather than the transcriber choice.

Next steps#