> For the complete documentation index, see [llms.txt](https://docs.kangal.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kangal.dev/gateway/quickstart.md).

# Publish your first API

This guide publishes one HTTP service through Kangal, verifies the public proxy path, and shows the exact failure signals to check before adding policies.

## Prerequisites

You need:

* a running Kangal control plane;
* an administrator token for one tenant;
* the tenant ID;
* a backend URL reachable from the runtime that will proxy traffic;
* `kangalctl`, available through the repository entrypoint `python scripts/kangalctl.py` when it is not installed as a command.

The examples use these shell variables:

```bash
export KANGAL_API_URL="https://control.example.com"
export KANGAL_ADMIN_TOKEN="replace-with-admin-token"
export KANGAL_TENANT_ID="tenant-acme"
export KANGAL_PROXY_BASE="https://proxy.example.com"
```

`KANGAL_API_URL` is the control-plane root used by `kangalctl`; the CLI appends the Admin API paths. `KANGAL_PROXY_BASE` is the reachable combined runtime or independent data-plane address. They may be the same in a combined deployment.

## 1. Configure the CLI context

```bash
kangalctl login \
  --api-url "$KANGAL_API_URL" \
  --token "$KANGAL_ADMIN_TOKEN" \
  --tenant-id "$KANGAL_TENANT_ID" \
  --context-name quickstart

kangalctl status
```

`status` checks `/health`, `/ready`, and the tenant-scoped gateway list. Verify the data plane and backend separately before sending production traffic.

## 2. Create a gateway

Use a payload such as:

```yaml
tenant_id: tenant-acme
name: orders-prod
description: Orders API production gateway
deployment_profile: serverless
plan_code: serverless_starter
labels:
  environment: production
  owner: platform
```

Create and list the gateway:

```bash
kangalctl create gateways -f gateway.yaml
kangalctl get gateways --tenant-id "$KANGAL_TENANT_ID"
```

Record the returned gateway `id`:

```bash
export KANGAL_GATEWAY_ID="replace-with-gateway-id"
```

The Console enforces a gateway name of at least three characters matching `^[a-z0-9][a-z0-9-_.]*$` and pairs the selected deployment profile with its plan code. The Admin API stores the supplied profile and plan metadata. Gateway creation also returns `proxy_host`, `proxy_url`, and workspace metadata. Treat the returned address as configuration metadata until public DNS and TLS checks succeed.

## 3. Create a direct service

A service can point directly to a URL or to an upstream pool. Start with a direct URL so route matching can be tested independently from load balancing.

```yaml
tenant_id: tenant-acme
name: orders-service
url: http://orders.internal:8080/api
retries: 2
connect_timeout_ms: 5000
read_timeout_ms: 15000
write_timeout_ms: 15000
labels:
  application: orders
```

```bash
kangalctl create services --gateway-id "$KANGAL_GATEWAY_ID" -f service.yaml
kangalctl get services --gateway-id "$KANGAL_GATEWAY_ID"
```

Record the returned service `id`:

```bash
export KANGAL_SERVICE_ID="replace-with-service-id"
```

The URL must include `http://` or `https://`. Alternatively, use `protocol`, `host`, `port`, and `path`; Kangal assembles those fields into a URL at runtime.

## 4. Create a prefix route

```yaml
tenant_id: tenant-acme
name: orders-public
path: /orders
path_type: prefix
methods:
  - GET
  - HEAD
service_id: replace-with-service-id
service_name: orders-service
hosts: []
snis: []
headers: {}
query_params: {}
strip_path: true
preserve_host: false
priority: 100
plugins: []
labels:
  exposure: public
```

Replace `service_id`, then create the route:

```bash
kangalctl create routes --gateway-id "$KANGAL_GATEWAY_ID" -f route.yaml
kangalctl get routes --gateway-id "$KANGAL_GATEWAY_ID"
```

Record the returned route `id` for later updates and cleanup:

```bash
export KANGAL_ROUTE_ID="replace-with-route-id"
```

With this configuration, a request for `/orders/health` matches the `/orders` prefix. Because `strip_path` is `true`, Kangal sends `/api/health` to the service URL. If `strip_path` were `false`, it would send `/api/orders/health`.

## 5. Send traffic through the proxy

Until the edge host is mapped to the gateway, provide explicit scope headers:

```bash
curl -i \
  "$KANGAL_PROXY_BASE/proxy/orders/health?verbose=true" \
  -H "X-Tenant-ID: $KANGAL_TENANT_ID" \
  -H "X-Gateway-ID: $KANGAL_GATEWAY_ID" \
  -H "X-Request-ID: quickstart-001"
```

The public `/proxy/{path}` entrypoint does not require an administrator session. Consumer authentication is enforced by the plugins assigned to the route. Do not send `KANGAL_ADMIN_TOKEN` to the proxy.

The authenticated `/api/proxy/{path}` endpoint also exists for session-based traffic, but it is not the normal public consumer entrypoint.

## 6. Verify the result

Before adding authentication or rate limiting, confirm all of the following:

1. The response came from the expected backend and path.
2. The status is not `404`, `405`, `502`, or `503` from Kangal.
3. The backend received the expected query string.
4. `X-Request-ID` is present in the response or related traffic telemetry.
5. The gateway overview shows the service and route.
6. In an independent deployment, the required node is online and its current configuration version matches the desired version.

Then add an [upstream and targets](/gateway/upstreams-targets.md), a [traffic policy](/gateway/traffic-management.md), or consumer authentication.

## Common failures

### `400 X-Tenant-ID header is required`

The request host is not mapped to a gateway and no tenant header was supplied. Add both scope headers for testing, or configure the edge host mapping.

### `404 Route not found`

Check the proxy path after `/proxy`, `path_type`, host restrictions, SNI, header/query matchers, tenant, and gateway. An `exact` route for `/orders` does not match `/orders/health`.

### `405 Method not allowed for route`

Kangal found a route matching the other request criteria, but the method is not listed. `HEAD` is accepted when `GET` is allowed; other methods must be explicit.

### `502 Route service not resolved`

The route refers to a service ID or name that no longer exists in the same tenant and gateway. Repoint the route or recreate the service.

### `502 Upstream target not resolved`

The direct URL is missing, the referenced upstream does not exist, or no target has a usable HTTP/HTTPS URL. Target addresses without a scheme can be stored but cannot be proxied.

### `503 Data plane has no valid last-known-good configuration`

The independent node has not accepted a bundle. Inspect its current and desired versions, `last_config_ack_status`, NACK message, cache trust material, and control-plane connectivity.

### Control plane is ready but traffic still fails

Readiness of the management API, data plane, edge, and backend are separate. Check each hop in that order. A generated `proxy_url` alone is not a traffic readiness signal.

## Clean up safely

Delete resources in dependency order: route, service, then gateway. The gateway delete operation does not perform a full cascade of every related resource.

```bash
kangalctl delete routes "$KANGAL_ROUTE_ID" --gateway-id "$KANGAL_GATEWAY_ID"
kangalctl delete services "$KANGAL_SERVICE_ID" --gateway-id "$KANGAL_GATEWAY_ID"
kangalctl delete gateways "$KANGAL_GATEWAY_ID"
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kangal.dev/gateway/quickstart.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
