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

# Token grammar

> Every mock token shape, what it stands for, and where it resolves.

Read any mock token and know what it stands for without looking it up.

## Overview

A **mock token** is a string an agent fills in place of a real value. Agent
Vault's proxy replaces it with the real value inside its own browser, at the
moment of filling. Outside the proxy it is just text.

```text theme={null}
av_<kind>_<...parts>_<userId>
```

The trailing user id is part of the token. Copy tokens exactly as the
[token catalog](/reference/token-catalog) gives them.

## Token shapes

| Kind | Format | Example |
| - | - | - |
| Identity | `av_id_{first_name\|last_name\|full_name\|email\|phone}_{userId}` | `av_id_email_u7x2k` |
| Identity, labelled | `av_id_{label}_{field}_{userId}` | `av_id_work_email_u7x2k` |
| Identity, phone parts | `av_id_{phone_country\|phone_national}_{userId}` | `av_id_phone_national_u7x2k` |
| Identity, split phone (North America only) | `av_id_{phone_area\|phone_prefix\|phone_line}_{userId}` | `av_id_phone_area_u7x2k` |
| Identity, date of birth | `av_id_{dob\|dob_day\|dob_month\|dob_year\|dob_mdy\|dob_dmy}_{userId}` | `av_id_dob_u7x2k` |
| Identity, gender | `av_id_gender_{userId}` | `av_id_gender_u7x2k` |
| Identity, title | `av_id_title_{userId}` | `av_id_title_u7x2k` |
| Address | `av_addr_{label}_{street1\|street2\|city\|state\|zip\|country}_{userId}` | `av_addr_ship_street1_u7x2k` |
| Login | `av_login_{label}_{username\|email\|password}_{userId}` | `av_login_github_password_u7x2k` |
| Login 2FA | `av_login_{label}_totp_{userId}` | `av_login_github_totp_u7x2k` |
| Card number | `av_card_{n}_number_{userId}` | `av_card_1_number_u7x2k` |
| Card security code | `av_card_{n}_cvv_{userId}` | `av_card_1_cvv_u7x2k` |

Card expiry is never a token. Fill the real `expiryMonth` and `expiryYear` from
the catalog. Like the brand and last four digits, the expiry is not sensitive.

## Where each kind resolves

| Kind | Resolves on |
| - | - |
| Identity | An authorized destination |
| Address | An authorized destination |
| Login, including 2FA | The login's `website` or a subdomain of it, or an exact `extraWebsites` entry. Nowhere else |
| Card number and security code | Wherever the card's active agent cards allow, **and** only on an authorized destination |

An authorized destination is a site the account holder approved or added, a
login's website, or a host on an active allowlist agent card. See
[Destinations](/dashboard/destinations). Identity, address, card and security
code tokens check it on every fill, in addition to the agent card rules. On any
other site the fill pauses and asks the account holder. If they deny the site or
let the request expire, the fill is refused with `destination_unauthorized`.

The rules travel with the token, not with the tool that fills it. A login token
filled through `fill_checkout` is checked exactly as if it were filled through
`fill_login`. See [URL locking](/security/url-locking).

## Tokens are stable

Tokens are derived from the account and the record, not issued per session.

* They do not expire. Proxy sessions do.
* Rotating a password does not change its token.
* Enrolling 2FA does not change any of that login's other tokens.
* A token you cached last week still works today, as long as the record and
  field behind it still exist.

A token stops working when what it stands for goes away. A deleted card or login
gives `token_not_found`. So does an optional login field the account holder
removed: clearing a login's email or username retires its `tokens.email` or
`tokens.username`, and removing its authenticator secret retires `tokens.totp`.
Each also drops out of the catalog. Fetch a fresh catalog after the account
holder edits a login, and whenever a fill returns `token_not_found`.

### Renaming an address changes its tokens

An address token carries the address's label, and the label is how the token is
looked up. When the account holder changes an address's label, every token for
that address changes with it. A cached `av_addr_ship_street1_u7x2k` returns
`token_not_found` once `ship` is renamed, and the catalog lists the new
`av_addr_<new-label>_...` tokens instead. Fetch a fresh catalog after any address
edit.

The other labelled kinds:

| Kind | Can the label change? |
| - | - |
| Extra identity (`av_id_<label>_...`) | Not from the dashboard. To change it, the account holder deletes the identity and adds it again, which retires the old tokens and mints new ones |
| Login (`av_login_<label>_...`) | No. The label is set when the login is created. Editing the login's website keeps the label and every token |

## Tokens are inert outside the proxy

Type a token into a form through plain Playwright and the merchant receives the
literal string `av_card_1_number_u7x2k`. The checkout fails and nothing real is
exposed. That is why the catalog is safe to give an agent, and safe to appear in
its logs.

| A token is not | Why |
| - | - |
| A bearer credential | It only resolves inside the proxy, for its own account, on a site it is registered for |
| A secret | It can appear in a log by design |
| Per site | One token works wherever its credential is registered |
| Per session | Sessions expire. Tokens do not |
| Readable | Nothing ever turns a token back into its value for the agent |

## Split phone tokens

`phone_area`, `phone_prefix` and `phone_line` are views of the same stored number
as `phone`, for forms that ask for it in three boxes.

They resolve only for a ten-digit North American number. For any other number
they throw `token_not_found`, because the 3-3-4 shape does not exist elsewhere: a
UK area code is 2 to 5 digits and an Indian mobile has no area code at all.

For a number outside +1, use `phone_country` with `phone_national`, which resolve
for any country.

`phone` itself is the whole number in E.164 form, such as `+15550100134`, for a
phone saved with the current **Country code** and **Number** fields. An older
phone stored only as free text fills that text unchanged until the account
holder saves it again. See
[Older phone numbers](/dashboard/identity-and-addresses#older-phone-numbers).

All five phone parts are newer than `phone`. A catalog from a deployment that
predates them has no such keys, so check before filling.

## Card sequence numbers

The `n` in `av_card_{n}_...` comes from a per-account counter, minted for
uniqueness and display only. It never decides which rules apply: a card's rules
are found through the card's own record. Numbers are never reused, even after a
card is deleted.

<Note>
  If one mock card number matches several differently configured cards, the fill
  is refused with `card_blocked`. The result is the same on every attempt. Use a
  different card, or ask the account holder to remove the duplicate.
</Note>

## Refusals tied to the grammar

| Code | Cause |
| - | - |
| `token_not_found` | No record matches, **or** a token of the wrong kind was used where a specific kind was required |
| `cross_user_denied` | The user id in the token is not this key's account. Three within five minutes revoke the key |
| `scope_denied` | The record exists but is outside this key's scope |
| `login_blocked` | A login or 2FA token on a site it is not registered for |
| `merchant_blocked` | A card token on a site the card's agent card rules do not permit |
| `destination_unauthorized` | An identity, address, card or security code token on a site that is not an authorized destination |

Full list: [Error codes](/sdk/error-codes).

## Related

* [Token catalog](/reference/token-catalog)
* [URL locking](/security/url-locking)
* [Glossary](/reference/glossary)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.