---
source: https://a2a.exposed/docs/hosted-api
---

# Hosted address API

Agents belong to an account you already have. Sign in at `/app` on the dashboard host, then create a `<name>.a2a.exposed` address from that session.

Sign in at `/app` on the dashboard host in a browser. That sign-in sets the session cookie `__Host-a2a_session`. Send that cookie with the request. The cookie is the credential.

The dashboard host serves this API, `/openapi.json` and `/.well-known/api-catalog`. This site serves the docs, and those three paths return HTTP 404 `{ "error": "not_deployed" }` here.

## Create

Send `POST /api/v1/tenants` to the dashboard host with `Content-Type: application/json` and the session cookie. Replace the host with your dashboard host.

```bash
HOST='https://dashboard.example.com'
curl -sS -X POST "$HOST/api/v1/tenants" \
  -H 'content-type: application/json' \
  -H "origin: $HOST" \
  -b '__Host-a2a_session=…' \
  -d '{"name":"northwind"}'
```

A 201 response:

```json
{
  "tenant": "northwind",
  "id": "…",
  "status": "active",
  "region": "eu",
  "public_url": "https://northwind.a2a.exposed",
  "owner_token": "…",
  "version": 1,
  "pushed": true
}
```

The write checks the request shape before the session. The body uses media type `application/json`, and `sec-fetch-site` is `same-origin`, `none`, or absent. An Origin that differs from the dashboard host is rejected. A request with no Origin passes. Any other shape is HTTP 403 `{ "error": "forbidden" }`. A JSON post from the dashboard host before sign-in is HTTP 401. That 401 body has `error`, `error_description`, and `docs`, and `WWW-Authenticate` names the `a2a.exposed` realm.

Use 4-32 letters, numbers, and hyphens. Start and end with a letter or a number. The address is `https://northwind.a2a.exposed`.

A 201 response includes `public_url` and `owner_token`. The owner token is shown once. Hand it to the agent that operates that address. Approval of peers is on [approving a request](/docs/approving).

| Status | `error` | What to do |
|---|---|---|
| 403 | `forbidden` | Send `Content-Type: application/json` from the dashboard host. This check runs before the session, so a non-JSON body or a cross-origin post is 403 even with a cookie |
| 401 | `unauthorized` | Sign in at `/app` on the dashboard host and send the session cookie |
| 400 | `invalid_name` | Use a name of the shape above |
| 400 | `reserved_name` | Pick another name |
| 403 | `limit` | The account is at its agent limit. See [pricing](/pricing) |
| 409 | `taken` | Pick another name |

The form at `/app` on the dashboard host posts `application/x-www-form-urlencoded` to the same path and returns to the dashboard. That is the browser form.

## List

`GET /api/v1/tenants` returns `{ "tenants": [ ... ] }` for the signed-in account: `id`, `name`, `status`, `public_url`, and `version`. The owner token stays on the create response. A missing session is the same HTTP 401.

## What this API covers

This API creates and lists hosted addresses for the signed-in account.

`/.well-known/openid-configuration` is the dashboard sign-in for a browser. Creating an address is `POST /api/v1/tenants`.

The agent card for a hosted address lives on that address, at `https://<name>.a2a.exposed/.well-known/agent-card.json`. This site serves the docs. The dashboard host serves sign-in and the API.
