Docs index: /llms.txt · every page as Markdown: add .md

‹ Overview

Keep your API secret off the device

Keep the API secret on your backend and out of the shipped app.

Creator plan or higher

Your API secret can create agents, start sessions, spend your credits and create more secrets. Anything you ship to a user’s device can be read by that user: a string in the app bundle, a value in the app’s preferences, or a header the app sends. Keep the secret on a server you run, and give devices the least they need.

Why it matters

  • A secret in a shipped app is shared by every install. Revoking it stops every copy of the app at once.
  • Whoever extracts it is billed as you: their sessions land on your account next to your users’ sessions.
  • A new build does not remove a leaked secret from old builds. Only revoking it does.

Pick a pattern

Your appWhere the avatar rendersWhat the device holds
A web page or a web viewthe browsernothing for a public agent; an embed token for a private one
Any app with a LiveKit clientbitHuman cloud or your serversa LiveKit room token from your server (Build a LiveKit agent)
The Swift package or the Android SDKthe devicethe API secret, in memory, fetched from your backend (below)

The first two patterns keep the secret on your backend: your server mints a short-lived token with the secret and the device presents only that token.

On-device rendering

The Swift package and the Android SDK report usage with the credential you pass to Expression2Credential.set or Essence2Credential.set. That credential is your API secret, so the device needs it in memory while it renders. You can still keep it out of the binary and limit what a leak costs.

Treat that secret as exposed in any build you ship: what a shipped app holds has the rules. In short, fetch it from your backend at launch, give each app its own secret, and watch your balance.

Serve the secret from your backend

Your backend checks your own user’s sign-in, then returns the secret. The app calls it at launch and passes the answer to the setter.

# Your backend: returns the secret only to a signed-in user of your app.
import os

def bithuman_credential(request):
    require_signed_in_user(request)  # your own auth check
    return {"secret": os.environ["BITHUMAN_API_SECRET"]}
// Your app: fetch at launch, keep in memory, never write it to disk.
struct Credential: Decodable { let secret: String }

let (data, _) = try await URLSession.shared.data(for: yourSignedInRequest)
Expression2Credential.set(try JSONDecoder().decode(Credential.self, from: data).secret)

On Android, call Expression2Credential.set(secret) (or Essence2Credential.set(secret)) with the value before fetch() and create().

This keeps the secret out of the app bundle and source control, and lets you rotate it without shipping a build. It does not stop a signed-in user from reading it from memory, so pair it with the steps below.

Limit what a leak costs

  • Give this app its own API secret, used by nothing else, so you can revoke it alone.
  • Rotate it on a schedule: create the new secret, point your backend at it, then revoke the old one (Rotate a secret).
  • Watch your balance and revoke at once if usage looks wrong.

Next