> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kviria.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Endpoint

> The single agent endpoint - wallet sign-in, request, response, and decisions.

The one endpoint. Your wallet is your account: every call carries a
CAIP-122 sign-in in the `SIGN-IN-WITH-X` header (domain
`api.kviria.com`, URI `https://api.kviria.com`, a fresh single-use
nonce per request). The `x-kviria-agent` header (or `?agent=`) is a
namespace label that isolates your agent's context — it is not a
secret.

```
POST https://api.kviria.com/v1/agent
Content-Type: application/json
Body limit: 16 KB
```

The authoritative wire schema (JSON Schema, MCP-ready) lives at
[kviria.com/tool-definition.json](https://kviria.com/tool-definition.json).
Your first 50 turns each day are free; beyond that, pay per turn —
see [Payments](/api/payments).

## Building the sign-in

The `SIGN-IN-WITH-X` header is a CAIP-122 payload, signed by your
wallet and base64-encoded. Build it per request — every nonce is
single-use.

**1. Build the payload:**

```json theme={null}
{
  "domain": "api.kviria.com",
  "address": "0xYourWalletAddress",
  "uri": "https://api.kviria.com",
  "version": "1",
  "chainId": "eip155:8453",
  "type": "eip191",
  "nonce": "a fresh random value",
  "issuedAt": "2026-09-09T12:00:00.000Z"
}
```

**2. Sign the EIP-191 message it describes** (the standard SIWE
text — `domain`, `address`, `URI`, `version`, `Chain ID: 8453`,
`Nonce`, `Issued At` lines) with your wallet's personal-sign.

**3. Add the `signature`, base64 the JSON, send it:**

```bash theme={null}
curl -X POST "https://api.kviria.com/v1/agent?agent=my-agent" \
  -H "Content-Type: application/json" \
  -H "SIGN-IN-WITH-X: $SIWX" \
  -d '{ ... }'
```

If you use the [x402 TypeScript SDKs](https://docs.x402.org),
`@x402/extensions/sign-in-with-x` provides the helpers
(`createSIWxMessage`, `signEVMMessage`, `encodeSIWxHeader`) so
the three steps are two lines of code.

## Request body

| Field          | Type   | Notes                                                                        |
| -------------- | ------ | ---------------------------------------------------------------------------- |
| `transcript`   | string | The user's raw words - or `intent`, never both                               |
| `intent`       | object | The structured meaning your LLM mapped (see below)                           |
| `anchor`       | object | The user's current position `{lat, lng}` - **required**                      |
| `candidates`   | array  | Echo the previous candidates verbatim                                        |
| `references`   | array  | Previously resolved `{gers, name}`, most-recent first (max 5)                |
| `frame`        | object | The last street context                                                      |
| `rangeM`       | number | Search radius, 50-1000 (default 100)                                         |
| `confirmation` | string | `"on"` (default) or `"off"` - the [confirm gate](/how-it-works/confirm-gate) |

## The structured intent

Your agent can do the mapping itself and skip the transcript entirely -
zero model calls on Kviria's side, fully deterministic. The actions:

`search`, `find`, `select`, `confirm`, `neighbors`, `across`,
`along`, `at_address`, `street_zoom`, `street_end`, `near`

```json theme={null}
{
  "intent": { "action": "search", "categoryAny": ["cafe"] },
  "anchor": { "lat": 37.76326, "lng": -122.4152 }
}
```

Anchors resolve from Kviria's own data only: a `ref` (a previous
response's id), a `name` exactly as returned, an `index` into the
echoed candidates, or `at` coordinates. Invalid intents return a
strict `400` that names the bad field - fix it and retry once.

## Response

| Decision     | Meaning                                      |
| ------------ | -------------------------------------------- |
| `resolved`   | One match, final                             |
| `confirm`    | One candidate, waiting for the user's yes/no |
| `candidates` | Several matches                              |
| `notFound`   | No match (may carry the absent `category`)   |
| `clarify`    | The reference was too vague                  |

`target` carries the outcome: `gers` (stable id), `name`, `category`,
`location {lat, lng}`, `distanceM` - and `address: {number, street}`
when the match is a door. A door resolves as `resolved` without the
confirm gate: an exact address verifies itself.

`evidence` is the audit trail - see
[Determinism & evidence](/how-it-works/determinism).
