# Getting Started with API Gateway - Agent

<WizardSteps build="gateway" method="agent" />

<MethodTabs build="gateway" method="agent" />

Put a managed gateway in front of any REST API. This path builds it with an AI
coding agent.

## Create your project

:::note{title="Requirements"}

[Node.js](https://nodejs.org/en/download) 24.0.0 or higher, a
[Zuplo account](https://portal.zuplo.com), and an installed coding agent.

:::

<Stepper>

1. **Create a local and hosted project**

   Run:

   ```bash
   npx create-zuplo-api@latest example-project
   cd example-project
   ```

   When prompted, choose **Yes** to create a matching Portal project, complete
   sign-in, and select your Zuplo account. Select the coding agent you use when
   asked. The CLI creates a project in the Portal and links your local
   `example-project` directory to its working copy. The hosted project stores
   the API key consumers and receives your deployment. If the CLI reports that
   project creation failed, run
   `npx zuplo project create --name example-project` from this directory. If
   linking failed, or after creating the hosted project, run `npx zuplo link`
   and select its working copy before continuing.

   :::tip{title="Zuplo skills"}

   The scaffold installs Zuplo skills in this project for Codex and Cursor and
   configures the Claude Code plugin. If setup fails, follow
   [Agent Skills](../../build-with-ai.mdx#agent-skills) from this directory
   before starting your agent. The project's `.mcp.json` also configures the
   Zuplo docs MCP server.

   :::

2. **Start the gateway**

   ```bash
   npm run dev
   ```

   Leave this running. The agent edits `config/` and `modules/`, and the dev
   server hot-reloads.

</Stepper>

## Hand it to the agent

One prompt covers the whole editor tutorial - forwarding, rate limiting, API key
authentication, and dynamic limits. Paste it into Claude Code, Cursor, or Codex
from inside your project directory.

<Stepper>

1. **Copy the prompt**

   ```text
   Read this project's agent instructions and the bundled docs in node_modules/zuplo/docs before writing code.

   Build a Zuplo API gateway in this project:
   1. Keep the default todo routes in config/routes.oas.json, but forward them to ${env.BASE_URL} and add BASE_URL=https://echo.zuplo.io to .env.zuplo.
   2. Add the rate-limiting inbound policy (rateLimitBy: ip, 2 requests / 1 minute) to every route.
   3. Add the api-key-inbound policy to every route, ordered before rate limiting.
   4. Make rate limiting dynamic: create modules/rate-limit.ts exporting rateLimit() that returns 1000 req/min for user.data.customerType === "premium", 5 for "free", 30 otherwise, and switch the policy to rateLimitBy: "function".
   5. Use the already-running dev server to verify with curl that GET /todos returns 401 without a key. I will create the free and premium keys in the Portal afterward; leave key-based tests for me.

   Explain each config change in one line and stop before pushing to git.
   ```

1. **Review what it changed**

   Expect edits to `config/routes.oas.json`, `config/policies.json`, a new
   `modules/rate-limit.ts`, and `.env.zuplo`. Open the local
   [Route Designer](../../articles/local-development-routes-designer.mdx) at
   http://localhost:9100 to see the policies on each route.

   :::tip

   Ask the agent to explain any policy option you do not recognize. It has the
   policy reference in `node_modules/zuplo/docs/policies/`.

   :::

</Stepper>

## Create an API key and test

The API key policy rejects everything until a consumer exists. Consumers live in
the Zuplo Portal, not in code.

<Stepper>

1. **Create two consumers**

   In the portal, open
   [**Services**](https://portal.zuplo.com/+/account/project/services) › **API
   Keys › Consumers › Create Consumer**. Create `free-consumer` with metadata
   `{ "customerType": "free" }` and `premium-consumer` with
   `{ "customerType": "premium" }`.

   :::warning

   Select the environment your local project is linked to with the **Dev /
   Preview / Prod** switcher. With a single environment, pick **Prod**.

   :::

1. **Test both limits**

   ```bash
   # no key -> 401
   curl -i http://localhost:9000/todos

   # free key -> 429 on the 6th request within one minute
   for i in 1 2 3 4 5 6; do
     curl -i http://localhost:9000/todos \
       --header 'Authorization: Bearer FREE_CONSUMER_KEY'
   done

   # premium key -> 1000 requests per minute
   curl http://localhost:9000/todos \
     --header 'Authorization: Bearer PREMIUM_CONSUMER_KEY'
   ```

   Replace `FREE_CONSUMER_KEY` and `PREMIUM_CONSUMER_KEY` with the keys from the
   Portal. The premium request should succeed; its limit is 1000 requests per
   minute, so a single request doesn't test the threshold.

</Stepper>

## Deploy

Zuplo deploys from Git. The agent can do the push; the connection happens in the
portal.

<Stepper>

1. **Ask the agent to push**

   ```text
   Commit everything, create an empty GitHub repo called example-project with gh, add it as origin and push main.
   ```

1. **Connect the repository in Zuplo**

   ```bash
   npx zuplo info
   ```

   Open the source-control link from the output, or **Settings › Source
   Control** in the portal. Click **Connect to GitHub**, then **Connect** on
   your repository. Zuplo deploys `main` immediately. Run `zuplo info` again to
   confirm.

   :::tip{title="Branch environments"}

   Every branch you push gets its own isolated environment. See
   [Branch-Based Deployments](../../articles/branch-based-deployments.mdx).

   :::

</Stepper>

## Wrapping up

You have built an API protected by API key authentication, dynamically rate
limited, deployed to the edge, and documented in your developer portal - with an
agent doing the configuration while you reviewed each change.

### Next steps

- Customize your [developer portal](../../dev-portal/overview.mdx) or explore
  [integrations](https://zuplo.com/integrations)
- [Grab time](https://zuplo.com/meeting) with the Zuplo team
- Start generating revenue with the
  [monetization tutorial](../../articles/monetization/index.mdx)
