> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inworld.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Security best practices

> How to keep Inworld API keys and tokens safe in web, mobile, and game clients.

Your API key is a long-lived workspace credential. Its permissions determine what it can access. Anyone who has it can make requests on your behalf, billed to your account, until the key is deleted. Follow these practices to protect it.

## Never ship an API key in client code

Anything you ship to users can be inspected, including browser JavaScript, Android APKs, iOS bundles, and game builds. TLS does not protect a key stored in the app itself. Treat any credential that has ever been in a client build as compromised. Delete the key in [Inworld Portal](https://platform.inworld.ai/api-keys) and create a new one.

API keys belong on servers you control:

- Store them in a secret manager, or as environment variables read at runtime.
- Keep them out of source control, build artifacts, and logs.
- Use separate keys per environment (development, staging, production), so revoking one does not take down the others.

## Two safe patterns for client apps

### Pattern A: proxy through your backend

The client talks only to your backend. Your backend holds the API key and calls Inworld:

```
Browser / mobile app  →  your backend (holds the key)  →  api.inworld.ai
```

This is the simplest model. Your backend gives you a place to handle your own authentication, quotas, and logging. No Inworld credential leaves your infrastructure. Each request adds a network hop, which can matter for streaming audio.

### Pattern B: mint a token, connect directly

For latency-sensitive streaming (TTS, STT, Realtime), let the client connect to Inworld directly, using a token instead of the API key. Your backend authenticates the user, creates a short-lived token with the key, and sends the token to the client:

```
Client  →  your backend: "give me a token"     (your own auth here)
Backend →  Inworld: mint token with API key
Client  →  api.inworld.ai with the token       (direct, low latency)
```

Two token types support this, in order of preference:

- **[One-time tokens](https://docs.inworld.ai/portal/ephemeral-tokens.md)** — single-use, short-lived (15 minutes by default). Each token authenticates exactly one connection or request, so a leaked token that was already used is worthless, and an unused one dies within minutes. Mint one per connection attempt.
- **[Session tokens](https://docs.inworld.ai/portal/session-tokens.md)** (deprecated) — multi-use JWTs that live for a few hours, still required for Realtime sessions. A leaked session token is usable until it expires and inherits all permissions assigned to its parent API key. Keep its exposure narrow and mint it from the narrowest key that fits (for example, a [Realtime-only key](https://docs.inworld.ai/portal/api-keys.md#realtime-only-api-keys)).

Your token endpoint controls access in this pattern. Authenticate users before creating tokens, and create them per user session. Never serve one cached token to everyone.

## If a credential leaks

1. **API key** — delete it in [Portal → API Keys](https://platform.inworld.ai/api-keys) and issue a new one. Deleting the parent key also invalidates every token minted from it.
2. **Token** — one-time tokens expire in minutes and die on first use; session tokens expire on their own. If you can't wait, delete the parent API key.
3. Review [usage](https://docs.inworld.ai/portal/usage.md) for activity you don't recognize.
