# Getting Started with AI Gateway - Portal

<WizardSteps build="ai-gateway" method="portal" />

Create an AI Gateway, send a chat request through it, and connect an OpenAI SDK
client. This tutorial uses the free Zuplo Demo provider, so you don't need a
provider API key.

## Prerequisites

- A [Zuplo account](https://portal.zuplo.com).
- A terminal with cURL to test the gateway from outside the Portal.

## Create and test your AI Gateway

<Stepper>

1. **Create an AI Gateway project**

   Open [**Projects**](https://portal.zuplo.com/+/account/projects), click **New
   Project**, and select **AI Gateway**. Name the project `my-ai-gateway` and
   click **Create Project**.

   <ModalScreenshot>

   ![New project dialog with AI Gateway selected](/media/ai-gateway-getting-started/create-project.png)

   </ModalScreenshot>

   When setup finishes, the project opens with **Create your first app**. The
   gateway is already deployed.

2. **Check the demo provider**

   Open
   [**Settings → AI Providers**](https://portal.zuplo.com/+/account/project/ai/settings/data-models).
   The new project includes **Zuplo Demo**, which provides test models without a
   provider API key. This tutorial uses `zuplodemo/pirate`.

   <ModalScreenshot>

   ![AI provider settings with the Zuplo Demo provider](/media/ai-gateway-getting-started/providers.png)

   </ModalScreenshot>

   The part before `/` names the provider; the part after `/` names the model.
   Later, use **Add Provider** to configure your own provider and its models.
   See [AI Providers](../../ai-gateway/providers.mdx).

3. **Create an app**

   Open [**Apps**](https://portal.zuplo.com/+/account/project/ai/apps) and click
   **Create App**. Enter `Tutorial app` as the **App name**. Keep the
   **Default** pool selected and click **Create app**.

   <ModalScreenshot>

   ![New app dialog with an app name and the Default pool](/media/ai-gateway-getting-started/create-app.png)

   </ModalScreenshot>

   An app represents the software that calls your gateway. Each app has its own
   URL and API key. The first app also creates the Default pool, which groups
   apps and supplies shared policy settings.

4. **Review authentication**

   Open the app's **Policies** tab. The new app inherits **API Key
   Authentication** from its pool. Keep this policy in place: requests must send
   the app's key in the `Authorization` header.

   <ModalScreenshot>

   ![App policy chain with inherited API Key Authentication](/media/ai-gateway-getting-started/policies.png)

   </ModalScreenshot>

   You can add policies for model filtering, budgets, and other controls here.
   For this first request, keep the default chain. See
   [Policy Chains](../../ai-gateway/policy-chains.mdx).

5. **Send a request in the Playground**

   Click **Playground** in the app header. Select `zuplodemo/pirate`, enter
   `Say hello`, and send the message. A pirate-themed reply confirms that the
   app can reach the provider through the gateway.

   <ModalScreenshot>

   ![AI Playground showing a successful response from the pirate demo model](/media/ai-gateway-getting-started/playground.png)

   </ModalScreenshot>

6. **Call the gateway from a terminal**

   In the **Playground**, click **Copy cURL**. Paste the copied command into
   your terminal and run it. The command includes the selected model, your
   conversation, and the app's API key. The response streams into the terminal
   as it arrives.

   Treat the copied command as a credential because it contains your API key.

</Stepper>

## Connect the OpenAI SDK

Copy **API URL** from the app header and the app's key from its **API Key** tab.
The URL includes the app ID after the hostname. Copy the complete URL without
adding `/v1` yet.

<ModalScreenshot>

![App API Key tab with the key concealed](/media/ai-gateway-getting-started/api-key.png)

</ModalScreenshot>

Set these values in your terminal, replacing the placeholders:

```bash
export ZUPLO_APP_URL="https://YOUR_GATEWAY.zuplo.app/YOUR_APP_ID"
export ZUPLO_APP_API_KEY="YOUR_APP_API_KEY"
```

With Node.js 24 or later installed, create a directory for the sample and
install the SDK in the same terminal:

```bash
mkdir ai-gateway-client
cd ai-gateway-client
npm init -y
npm install openai
```

Save this as `sample.mjs` and run `node sample.mjs` from the terminal where you
set the environment variables:

```javascript title="sample.mjs"
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: `${process.env.ZUPLO_APP_URL}/v1`,
  apiKey: process.env.ZUPLO_APP_API_KEY,
});

const result = await client.chat.completions.create({
  model: "zuplodemo/pirate",
  messages: [{ role: "user", content: "Say hello" }],
});

console.log(result.choices[0].message.content);
```

The OpenAI SDK uses the app URL with `/v1` appended. It sends the app key to
Zuplo; provider credentials stay in the gateway. See the
[OpenAI SDK integration](../../ai-gateway/integrations/openai.mdx) for more
examples.

## Troubleshooting

| Result                         | What to check                                                                                             |
| ------------------------------ | --------------------------------------------------------------------------------------------------------- |
| `401 Unauthorized`             | Use the app's API key, not a provider key. Include the `Bearer` prefix.                                   |
| `404`                          | Copy the complete app URL, including its app ID, then append `/v1/chat/completions`.                      |
| Model not found or not allowed | Use `zuplodemo/pirate` and confirm Zuplo Demo is enabled. If you added Model Filtering, allow this model. |

## Next steps

- [Add providers](../../ai-gateway/providers.mdx) to connect your own models.
- [Configure policy chains](../../ai-gateway/policy-chains.mdx) to restrict
  models or add budgets and guardrails.
- [Connect source control](../../ai-gateway/source-control.mdx) to deploy code
  changes from Git.
