Run the voice or the model on your own vendor account. How your keys are encrypted, where they are used, and what never leaves our servers.
By default your avatars speak and think on AvatarFactory's provider accounts, metered against your plan. Bring-your-own-key (BYOK) points a slot at your account with a vendor instead — so the vendor bills you directly, and you get access to models and voices we do not resell.
There are two independent slots. You can bring a key for one, both, or neither.
| Slot | Providers | What your key pays for |
|---|---|---|
| Voice | ElevenLabs, Inworld | The speech synthesis. Calls on your own voice key do not draw platform minutes. |
| Brain | OpenAI, Anthropic, Google | The language model only. Platform minutes still apply — you are paying the model vendor, not replacing the session. |
Voice BYOK and brain BYOK are metered differently, and the difference matters. Your own voice key exempts those calls from platform minutes. Your own brain key covers the model cost, but the session is still metered as normal. Do not budget as though brain BYOK makes a session free.
Groq never takes a customer key. It is a host for open-weights models, not a vendor account you hold, so there is nothing to bring. Groq models always run on the platform tier.
This is the part worth being precise about, so here is exactly what happens to a provider key from the moment you paste it.
The key is checked against the shape that provider issues — sk_ for
ElevenLabs, sk- for OpenAI, sk-ant- for Anthropic, AIza for Google, and a
minimum length for Inworld's opaque credentials. A malformed key is rejected
before anything is written, with an error naming the expected shape.
The plaintext key never reaches the database. It is sealed with AES-256-GCM using a 256-bit server key held only in the server environment — never in the codebase, never in a client bundle.
Every secret gets its own random 96-bit initialization vector, so two identical keys encrypt to different ciphertext. GCM is authenticated encryption: an authentication tag is stored alongside the ciphertext, so tampering with the stored bytes makes decryption fail loudly instead of silently returning garbage.
Each stored credential records which encryption key sealed it. That is what makes rotation possible: we can introduce a new server key and roll forward without a bulk re-encryption pass over existing secrets, and without a window where old credentials cannot be read.
Once saved, the API that lists your credentials returns the label, the provider, the status, and the dates. It does not return the secret, the ciphertext, or even a prefix — a provider key's prefix can itself be identifying, so we do not show one. The only way to change a key is to add a new one and delete the old.
| Component | Sees your provider key? |
|---|---|
| Our call server, at session time | Yes — decrypted in memory for the duration of the call to authenticate to the vendor, and never persisted in plaintext. |
| The SDK in your user's browser or app | No. The key is resolved server-side from your account. It never travels through the SDK, the config object, or the WebSocket. |
| A deployment or Framer embed | No. The binding lives on the avatar, so a public embed with no credential in its request path still resolves to the right account. |
| Our dashboard, after you save it | No. The browser never receives it back. |
| Logs and error reports | No. Audit entries record that a key was saved and which provider it was for — never the value. |
The SDK flags useOwnVoice and useOwnBrain are switches, not carriers.
They tell the server "bill this to my account"; the server does the lookup. A
key in your client config would be a key in your client bundle, which is why
the API is shaped this way.
Profile → Developer → Your provider keys → Add provider key.
Pick the provider, give the key a name you will recognise later, and paste the secret. Each provider's hint tells you where to find it in that vendor's own dashboard.
You can hold as many keys per provider as you like — a separate one per environment or per client, say. The first key you add for a provider automatically becomes that provider's default, so adding exactly one key never requires discovering that a second step exists. Use Set as default to move it later.
You can also add a key inline while configuring an avatar: the Brain and Voice panels offer Add key at the point you need one, and the key you add is bound to that slot immediately rather than making you go and reselect it.
| Action | Effect |
|---|---|
| Disable | The key stops being selectable and stops being used, but stays on the account. Reversible — re-enable it at any time. |
| Set as default | Makes it the key a slot resolves to when it is set to “Platform key (or your default)”. One default per provider. |
| Delete | Permanent. If avatars are still bound to the key, you are told which before it is removed — deleting anyway leaves those avatars to fall back to the platform key, or to fail if the model is BYOK-only. |
Provider keys live on your account; which key a given avatar uses is chosen on the avatar. That split is what lets one account run several clients' avatars on several different vendor accounts.
In the Platform, open an avatar and use the Brain or Voice tab. The API key field lists your active keys for that provider, plus a Platform key option:
Some models are BYOK-only: we hold no key for them at all, so the platform option is not offered and the field is required. The panel tells you which provider key the model needs and lets you add it there and then.
You rarely need these — the binding on the avatar is usually the right place, and it is the only thing a public embed can use. Set them when one integration should differ from what the avatar was published with.
Leaving a flag out is not the same as setting it to false. Omit it and the
binding on the avatar decides — that is the normal case, and the only one an
embed can use. true forces your key; false vetoes it for that integration
and runs on the platform key even if the avatar binds one.
When you have asked for your key — either by setting the flag to true or by
binding one on the avatar — and no usable credential is found, the session is
rejected rather than quietly moved onto the platform key, so a deleted or
disabled credential surfaces instead of silently changing who is billed. Only an
avatar with no binding at all falls back to the platform key.
Bring-your-own-key requires a plan that includes it, and is not available on test keys. Sessions on a plan without it run on the platform key; on a BYOK-only model, where there is nothing to fall back to, they are rejected.
A key you bring is a key you are billed for, directly by that vendor, outside your AvatarFactory plan. Set spend limits in the vendor's own dashboard — AvatarFactory cannot cap spending on an account it does not own.
af_test_* and af_live_* keys that
authenticate you to us. Different thing, different rules.