Skip to main content
The SDK authenticates with our backend before it enhances audio. How you supply that credential depends on where the SDK runs. There are two approaches, and most users only need the first.
  • Server-side authentication (SDK key). Embed your SDK key directly in a trusted environment you control. This is the simple path and all most users need to get started.
  • Client-side authentication (token minting). When the SDK runs on untrusted clients (browsers, mobile, end-user devices), mint short-lived JWT tokens from your backend and hand those to the client, so the long-lived SDK key never leaves your servers.

Use the SDK key directly

The SDK runs in a trusted environment you control, such as your own servers or backend. The key stays in a place clients cannot reach. Jump to the SDK key setup.

Use short-lived JWT tokens

The SDK runs on untrusted clients you do not control. Mint tokens from your backend so the SDK key never ships to the client. Jump to token minting.

Server-side authentication

For trusted, server-side environments, an SDK key is all you need to get started.

Get an SDK License

Self-service SDK Keys can be generated on the developer platform. These keys are configured to authorize with our backend and collect telemetry. Pass the key straight to the processor exactly as the Quickstart shows. Because the key stays on a backend clients cannot reach, there is nothing else to do. If your SDK runs anywhere a client could read it, use the token minting approach below instead.

Client-side authentication

Anything you ship to a client can be extracted. A license key baked into a browser bundle or edge binary is one strings command away from leaking. So don’t ship it. Keep your SDK license on your backend, use it to mint short-lived JWTs, and hand those to clients instead. A JWT drops in exactly where a license key would, and you can swap it for a fresh one before it expires without recreating the processor or reloading the model.
JWT-form license keys and update_bearer_token() were introduced in SDK 0.19.0, which ships in the Python aic-sdk binding from version 2.3.0 onward.
1

Decode API key from SDK license

Self-service SDK Keys can be generated on the developer platform. This key stays on your backend, where clients never see it.The credential the platform gives you is a signed token of the form <payload>.<signature>, where the payload is base64-encoded JSON. Decode that payload once at startup to read the api_key field inside it:
import base64, json, os

raw = os.environ["AIC_SDK_LICENSE"]          # signed "<payload>.<signature>" from the platform
payload = raw.split(".")[0]                  # the first segment is base64-encoded JSON
api_key = json.loads(base64.b64decode(payload))["api_key"]
# payload shape: {"user": "user_...", "version": "2", "api_key": "..."}
raw is the license key the SDK accepts directly, exactly as the Quickstart passes it to aic.Processor(...); don’t try to decode it before handing it to the SDK. The inner api_key is what the token endpoint expects. In this tutorial the client never touches either one; it only ever sees the JWT you mint below, so reach for api_key here and leave raw on the backend.
These keys are configured to authorize with our backend and collect usage telemetry.
2

Mint a token on your backend

Exchange your API key for a short-lived JWT by calling the token endpoint. Run this server-side so the credential never reaches the client, then return the token to your app over your own API.
import requests

TOKEN_ENDPOINT = "https://api.ai-coustics.io/v1/sdk/tokens"

def mint_token(api_key: str) -> str:
    """Exchange the API key for a short-lived JWT (~1 hour TTL)."""
    response = requests.post(
        TOKEN_ENDPOINT,
        auth=(api_key, ""),  # HTTP Basic: api_key as username, empty password
        timeout=10,
    )
    response.raise_for_status()
    return response.json()["token"]
3

Initialize the SDK with the token

Pass the JWT in place of the license key.
import aic_sdk as aic

model_path = aic.Model.download("quail-vf-2.1-l-16khz", "./models")
model = aic.Model.from_file(model_path)
config = aic.ProcessorConfig.optimal(model, num_channels=2)

# The JWT goes exactly where a license key would.
processor = aic.Processor(model, mint_token(api_key), config)
processor_context = processor.get_processor_context()
Creating the processor with a minted JWT is what makes the in-place refresh in the next step possible. update_bearer_token() only swaps a token when both the originally configured key and the new one are JWTs. If you initialize with a plain license key instead, the swap leaves the existing token in place and raises TokenUnsupportedError.
4

Refresh before the token expires

Tokens currently last about an hour, but it could change in the future. Each token tells you when it expires: the exp claim inside the JWT, mirrored by the expires_at field the token endpoint returns. Derive your refresh time from it and swap the new token in a little before it passes with update_bearer_token() on the processor context. There is no need to recreate the processor or reload the model, and the call is safe to make while audio is processing.
import base64, json, time

REFRESH_MARGIN = 300  # swap the token in 5 minutes before it expires

def token_expiry(token: str) -> int:
    """Read the JWT's `exp` claim (Unix seconds)."""
    payload = token.split(".")[1]                 # the JWT payload segment
    payload += "=" * (-len(payload) % 4)          # restore base64url padding
    return json.loads(base64.urlsafe_b64decode(payload))["exp"]

# Run this on a background thread; each token's own expiry sets the next wait.
while True:
    token = mint_token(api_key)
    processor_context.update_bearer_token(token)
    time.sleep(max(0, token_expiry(token) - time.time() - REFRESH_MARGIN))
If a token expires before you swap in a fresh one, processing raises LicenseExpiredError. Mint a new token and retry; the proactive refresh above keeps you clear of this. The only case where enhancement actually stops is a revoked or otherwise unauthorized key, which surfaces as EnhancementNotAllowedError. Even then the SDK fails soft: the audio passes through unprocessed and the algorithmic delay is preserved, so the stream is never interrupted. Bypassed audio is tracked by the usage.disallowed and processor.bypass metrics (learn more on the Observability page).
5

Find out more

SDK Quickstart

Real-time speech enhancement with the SDK in your preferred language.

Developer Platform

Generate SDK license keys and explore the SDK playground.

Telemetry

What the SDK reports back and how authorization works.

Python SDK Examples

More examples, including real-time processing and analysis.