# Quickstart

Get an API key, send a request, and stream the answer. You need a Gateway organization: API keys belong to one.

## 1. Get an API key

An API key belongs to a Gateway organization, and only its owner can create one, while signed in: in [Settings › API keys](/settings/gateway/api-keys), or with `POST /organization/apikeys`. The key is shown once. No Gateway organization yet? [Create one](/organization/new/gateway). [Authentication](/docs/gateway/authentication/) has the details.

> **Keep keys on your server**
> Anyone with the key can spend your organization’s credits. Don’t put it in a browser or a mobile app.

```bash title="Terminal"
export MOMOR_API_KEY="…"
```

## 2. Send a request

Point any OpenAI-compatible SDK at the `/v1` address below and use your Momor key. Ask for a model by its ID from the [model catalog](/docs/gateway/models/).

```bash
curl https://api.momor.ai/v1/chat/completions \
  -H "Authorization: Bearer $MOMOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4-mini",
    "max_tokens": 1024,
    "messages": [
      { "role": "user", "content": "Summarise this contract in three points." }
    ]
  }'
```

```python
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.momor.ai/v1", api_key=os.environ["MOMOR_API_KEY"])

reply = client.chat.completions.create(
    model="openai/gpt-5.4-mini",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Summarise this contract in three points."}],
)
print(reply.choices[0].message.content)
```

```typescript
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.momor.ai/v1", apiKey: process.env.MOMOR_API_KEY });

const reply = await client.chat.completions.create({
  model: "openai/gpt-5.4-mini",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Summarise this contract in three points." }],
});
console.log(reply.choices[0].message.content);
```

```csharp
using System.ClientModel;
using OpenAI;
using OpenAI.Chat;

var client = new ChatClient(
    model: "openai/gpt-5.4-mini",
    credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("MOMOR_API_KEY")!),
    options: new OpenAIClientOptions { Endpoint = new Uri("https://api.momor.ai/v1") });

ChatCompletion reply = await client.CompleteChatAsync(
    [new UserChatMessage("Summarise this contract in three points.")],
    new ChatCompletionOptions { MaxOutputTokenCount = 1024 });
Console.WriteLine(reply.Content[0].Text);
```

The answer is a standard chat completion, with `model` naming the model that served it. Its `id` is the call’s request id, also sent in the `X-Momor-Request-Id` header: read the call back with [Get a generation](/docs/gateway/reference/generation/) to see each provider tried and what each attempt cost.

## 3. Stream the answer

Set `stream` to `true` to receive the answer as server-sent events. The `X-Momor-Provider` and `X-Momor-Model` headers name who is answering. A provider that fails before it sends anything is passed over for the next one; once output has begun, a failure ends the stream with an error chunk, and the call is not restarted on another provider. Momor’s own API can [roll over](/docs/gateway/failover/) instead.

```bash
curl https://api.momor.ai/v1/chat/completions \
  -H "Authorization: Bearer $MOMOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4-mini",
    "max_tokens": 1024,
    "stream": true,
    "messages": [
      { "role": "user", "content": "Summarise this contract in three points." }
    ]
  }'
```

```python
stream = client.chat.completions.create(
    model="openai/gpt-5.4-mini",
    max_tokens=1024,
    stream=True,
    messages=[{"role": "user", "content": "Summarise this contract in three points."}],
)
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="")
```

```typescript
const stream = await client.chat.completions.create({
  model: "openai/gpt-5.4-mini",
  max_tokens: 1024,
  stream: true,
  messages: [{ role: "user", content: "Summarise this contract in three points." }],
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
```

```csharp
await foreach (StreamingChatCompletionUpdate update in client.CompleteChatStreamingAsync(
    [new UserChatMessage("Summarise this contract in three points.")],
    new ChatCompletionOptions { MaxOutputTokenCount = 1024 }))
{
    foreach (ChatMessageContentPart part in update.ContentUpdate)
    {
        Console.Write(part.Text);
    }
}
```

## 4. Let Gateway choose

Instead of one model, add more in `models`. Gateway tries every model `model` names, then each entry of `models` in order, and moves on when one can’t serve the call. A selector can be a model ID, a publisher’s model, or a tier such as `tier/high`; see [choosing a model](/docs/gateway/choosing-a-model/).

```json title="Request body"
{
  "model": "anthropic/claude-sonnet-5",
  "models": ["openai/gpt-5.6-terra", "tier/high"],
  "max_tokens": 1024,
  "messages": [{ "role": "user", "content": "…" }]
}
```

## Next

- [Model catalog](/docs/gateway/models/): Pick models by what they can do and what they cost.
- [API reference](/docs/gateway/reference/chat-completions/): Every field Gateway reads and returns, and its errors.
