# Use the API > Create a key in the portal and send an OpenAI-compatible request. Section: Start. Web page: https://docs.katara.com/start/api/ The API follows the OpenAI chat completions shape. Most clients only need a new base URL and a key. ## Create a key Sign in to the portal at `https://platform.katara.com` and open **API Keys**. Create an organization if you do not have one and select an environment: **Test** while you build, **Live** for real traffic. Enable the Cortex **inference** permission, choose a name, an expiry date and a payment method, then create the key. Copy it immediately; its secret is shown once. The environment decides where the key's requests are served and paid. A Live key pays from Account Credits or in USDC on Avalanche C-Chain from your wallet. Credits need no wallet: a new account starts with a signup credit, and you can buy more by card under **Billing**. A Test key pays in test USDC on Avalanche Fuji from your wallet, or with the Test environment's test credits, 5 a day with no value; Account Credits do not pay for Test model calls. [Networks](https://docs.katara.com/about/networks.txt) compares the two. A key belongs to one organization and one environment. The same key can carry explicit Synapse and Locus permissions. Choosing those permissions does not grant spending authority or bypass approvals. An agent's paid model calls in Test are Test Compute: they are paid by the run's budget, in Account Credits or in test USDC, under the run's consent and limits, whatever the key pays with. Revoked and expired keys are refused on subsequent requests. Issue a replacement with the required scopes and expiry to rotate a key. When 80% of a key's lifetime has passed, Katara reminds the person who created it, unless they have already created a key with the same name in the same environment that lasts longer. Wallet payment methods still require the wallet's spending approval; a key with no inference permission needs no wallet. A key's prefix names its environment: keys from a Live environment start with `kat_live_`, keys from a Test environment with `kat_test_`. Keys created before the prefixes followed the environment keep the prefix they were issued with and keep working in the environment they belong to. ## Send a request ```sh curl https://api.katara.com/v1/chat/completions \ -H "Authorization: Bearer $KATARA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "katara/cortex", "messages": [{"role": "user", "content": "Explain a Merkle tree in two sentences."}], "max_tokens": 200 }' ``` [Katara Cortex](https://docs.katara.com/concepts/cortex.txt) picks a model for the request and keeps answering when a provider goes away. A client that sends its own default model name needs no change ([Model names in requests](https://docs.katara.com/concepts/models.txt#model-names-in-requests)). The reply carries a `katara` object with the charge. A key that pays with credits sees it in Credits, under the legacy field name `cost_usd`: ```json "katara": { "billing_method": "credits", "cost_usd": "0.000018" } ``` A key that pays with USDC sees the settled price in USDC and the provider's address: `"cost_usdc": "0.000018", "provider": "0xfFe5…38DC"`. [Usage and costs](https://docs.katara.com/developers/usage.txt) lists every field. Send it with a Test key and the same request runs on Avalanche Fuji; the address does not change. ## With the OpenAI client ```python import os from openai import OpenAI client = OpenAI(base_url="https://api.katara.com/v1", api_key=os.environ["KATARA_API_KEY"]) reply = client.chat.completions.create( model="katara/cortex", messages=[{"role": "user", "content": "Hello"}], ) print(reply.choices[0].message.content) ``` Streaming works the same way with `stream=True`. The final chunk before `[DONE]` has an empty `choices` array and carries the `katara` charge. Tool calling follows the OpenAI shape too, and Katara can search the web for the model; see [Tool calling](https://docs.katara.com/developers/tools.txt). `client.responses.create(model=..., input=...)` works with the same key. Responses are stored for 30 days unless you send `store=False`, so `previous_response_id` continues a conversation. [Responses](https://docs.katara.com/developers/responses.txt) lists what it takes. ## Other clients The same key works in the clients that speak these formats: - **Anthropic SDKs and Claude Code**: base URL `https://api.katara.com` (no `/v1`). For Claude Code, set `ANTHROPIC_BASE_URL=https://api.katara.com` and put the key in `ANTHROPIC_API_KEY`. See [Messages](https://docs.katara.com/developers/messages.txt). - **OpenAI SDKs, LiteLLM, LangChain and the Vercel AI SDK**: base URL `https://api.katara.com/v1`, with any model name. - **Cursor**: turn on the custom OpenAI base URL in its model settings, enter `https://api.katara.com/v1`, and use the key as the OpenAI API key. Every model name a client sends is served by Cortex, so a client's default model needs no change. ## List models `GET /v1/models` needs no key and returns `katara/cortex` with its capabilities, context window and price ceiling. The list also carries `katara/cortex-genius` and `katara/cortex-smart`, which only requests paid per call with [x402](https://docs.katara.com/developers/x402.txt#choosing-a-model) may name; a key that names them is refused. See the [API reference](https://docs.katara.com/api.txt) for the full shapes and the error codes.