# Core concepts

This page explains the key domain concepts you will encounter when working with the Vilna API. Each section describes what the concept is, how it is identified, and when you will use it. For full endpoint details, see the [Platform API Reference](/apis/platform/).


```mermaid
flowchart TD
    BC["Blockchain<br/>eip155:1"] -->|has| ADDR["Address<br/>0x..."]
    BC -->|has| TOK["Token<br/>CAIP-19"]
    ADDR -->|participates in| TX[Transaction]
    TX -->|contains| EV["Events<br/>transfer, fee, ..."]
    EV -->|produces| ACT["Activity<br/>in/out + delta"]
    ADDR -->|has| BAL[Balances]
    NC["Notification Channel<br/>Webhook / Telegram"] -->|delivers| EV
    PK["Public Key<br/>xPub"] -->|derives| ADDR
```

## Blockchains and chain IDs (CAIP-2)

Vilna identifies every blockchain with a [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md) global identifier (GID). The format is `namespace:reference` - for example, `eip155:1` for Ethereum mainnet or `eip155:137` for Polygon.

You can list all supported chains with [`GET /blockchains`](/apis/platform/api/blockchain/list-blockchains).

Common chain GIDs:

| GID | Chain |
|  --- | --- |
| `eip155:1` | Ethereum |
| `eip155:56` | BNB Smart Chain |
| `eip155:137` | Polygon |
| `eip155:42161` | Arbitrum One |
| `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | Solana |


For the full CAIP standard reference, see [CAIP Standards](/apis/platform/caip-standards).

## Addresses

If you are new to blockchain addresses, keys, and derivation paths, see [Blockchain Basics](/guides/blockchain-basics) for a primer before continuing.

An address represents a blockchain account you want to monitor. There are two ways to add addresses:

**External addresses** are standalone accounts you import individually with [`POST /addresses/external`](/apis/platform/api/address/create-external-address). You provide the raw address value, a `chainFamily` (which assigns the address to all chains in that family automatically), and an optional label.

**HD-derived addresses** are generated from a public key (see the next section). These addresses are created sequentially and are automatically monitored once generated.

Supported address formats include:

| Format | Example chains |
|  --- | --- |
| `evm` | Ethereum, Polygon, Arbitrum, BSC |
| `p2pkh` | Bitcoin (legacy) |
| `p2sh` | Bitcoin (compatibility) |
| `p2wpkh` | Bitcoin (native SegWit) |
| `p2wsh` | Bitcoin (SegWit script) |
| `p2tr` | Bitcoin (Taproot) |
| `solana` | Solana |
| `tron` | Tron |


Every address has a `meta` field - a free-form JSON object where you can store application-specific data such as customer IDs, invoice numbers, or internal references. This metadata is returned in API responses and webhook payloads, so you can correlate blockchain events with your business logic.

### Resolving an address from a public key

If you have a raw public key and need the corresponding blockchain address, use [`POST /addresses/external/resolve`](/apis/platform/api/address/resolve-external-address). This endpoint computes the address from the public key, creates an external address, and returns it. The public key is used only for derivation and is not stored. If an address with the computed value already exists, the existing one is returned.


```bash
curl -X POST "https://api.vilna.io/v1/addresses/external/resolve" \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "publicKey": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
    "addressFormat": "evm"
  }'
```

The `publicKey` field accepts hex-encoded secp256k1 keys (compressed or uncompressed, with optional `0x` prefix) for EVM, Tron, and Bitcoin formats, or base58-encoded ed25519 keys for Solana. You can also pass optional `label` and `meta` fields, just like when creating an external address directly.

This is useful when your system stores raw public keys (for example, from hardware wallets or key ceremonies) and you need to derive and register the on-chain address without doing the computation yourself.

List all addresses with [`GET /addresses`](/apis/platform/api/address/list-addresses).

## Public keys and HD wallets

If you manage an HD wallet, you can import its extended public key (xPub, yPub, or zPub) with [`POST /public_keys`](/apis/platform/api/public_key/create-public-key). Vilna uses BIP-32 / BIP-44 / BIP-49 / BIP-84 / BIP-86 derivation paths to generate child addresses deterministically.

Once the public key is imported, call [`POST /public_keys/{public_key_id}/addresses/next`](/apis/platform/api/public_key/generate-next-public-key-address) to generate the next unused address in the derivation sequence. The new address is automatically registered for monitoring on the chains associated with the public key.

This approach is ideal for payment processors and exchanges that need a unique deposit address per customer without exposing the private key.

## Tokens and assets (CAIP-19)

Every token or coin is identified with a [CAIP-19](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-19.md) asset ID. The format is `chain_gid/asset_namespace:asset_reference`.

**Native tokens** use the `slip44` namespace:


```
eip155:1/slip44:60          - ETH on Ethereum
eip155:56/slip44:60         - BNB on BSC
```

**Contract tokens** use namespace matching the token standard:


```
eip155:1/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48   - USDC on Ethereum
eip155:56/erc20:0x55d398326f99059fF775485246999027B3197955    - USDT on BSC
```

Token metadata (name, symbol, decimals) is included in the `references.tokens` field of API responses.

## Transactions and events

A transaction represents a confirmed or pending on-chain operation. List transactions across all your addresses with [`GET /transactions`](/apis/platform/api/transaction/list-transactions).

Each transaction contains one or more **canonical events** that describe what happened:

| Event kind | Description |
|  --- | --- |
| `transfer` | Token or native currency moved between addresses |
| `utxo_transfer` | UTXO-based transfer with full input/output visibility (Bitcoin) |
| `fee` | Gas or network fee paid |
| `approval` | ERC-20 spend allowance granted or changed |
| `call` | Smart contract method invoked |
| `contract_create` | New smart contract deployed |


Events are the building blocks for understanding what a transaction did. A single swap transaction, for example, might produce multiple `transfer` events and a `fee` event.

## Activity

The activity feed ([`GET /activity`](/apis/platform/api/activity/list-activity)) is a higher-level view that shows balance changes for your monitored addresses. Each entry includes:

- **direction** - `in` (received) or `out` (sent)
- **amount** - how much was gained or lost (see Amounts below)
- **token** - which asset changed
- **address** - which of your addresses was affected


Use the activity feed when you need a simple "what came in, what went out" view without parsing raw transaction events.

## Balances

Query the current holdings of your addresses with [`GET /balances`](/apis/platform/api/balance/list-balances) (all addresses) or [`GET /addresses/{address}/balances`](/apis/platform/api/address/list-address-balances) (single address). The response lists each token held along with its amount.

Balances are updated automatically as new transactions are indexed.

## Amounts

All monetary values in the API are returned as an object with two fields:


```json
{
  "base": "1000000",
  "formatted": "1.0"
}
```

| Field | Description |
|  --- | --- |
| `base` | The raw integer amount in the token's smallest unit (e.g., wei for ETH, satoshi for BTC) |
| `formatted` | The human-readable decimal value after applying the token's decimal places |


Always use `base` for arithmetic and storage. Use `formatted` for display purposes only.

Use base for arithmetic
Always use `base` for calculations and storage. The `formatted` value is for display only and may lose precision for very large or very small amounts.

## Notification channels

A notification channel defines a destination for real-time event delivery. Vilna supports two channel kinds:

**Webhook** - Vilna sends an HTTP POST to your URL whenever a relevant event occurs. The request will include HMAC-SHA256 signature headers for verification (planned). See [Authentication](/guides/authentication#webhook-signature-verification) for signature details.

**Telegram** - Events are delivered to a Telegram chat.

Create a channel with [`POST /channels`](/apis/platform/api/channel/create-channel) and test it with [`POST /channels/{channel_id}/actions/test`](/apis/platform/api/channel/test-channel).

Channels are global to your project. All monitored addresses deliver events to all active channels.

## The references pattern

List and detail responses include a `references` object that contains related entities so you can resolve IDs without extra API calls.


```mermaid
flowchart LR
    API[API Response] --> ITEM[item / items]
    API --> REF[references]
    API --> META["meta<br/>page, limit, total"]
    REF --> TOKENS["tokens<br/>name, symbol, decimals"]
    REF --> CHAINS["blockchains<br/>name, gid"]
    REF --> ADDRS["addresses<br/>label, meta"]
    ITEM -.->|asset_gid| TOKENS
    ITEM -.->|chain_gid| CHAINS
```

For a single-item response:


```json
{
  "item": { "...": "..." },
  "references": {
    "tokens": { "eip155:1/slip44:60": { "name": "ETH", "...": "..." } },
    "blockchains": { "eip155:1": { "name": "Ethereum", "...": "..." } },
    "addresses": { "eip155:1:0x742d...": { "...": "..." } }
  }
}
```

For a list response:


```json
{
  "items": [ "..." ],
  "meta": {
    "limit": 30,
    "page": 1,
    "total": 142,
    "total_pages": 5
  },
  "references": { "...": "..." }
}
```

The `meta` object provides pagination info. Use the `limit` and `page` query parameters to navigate pages.

## Errors

The API returns errors in [RFC 7807](https://tools.ietf.org/html/rfc7807) `application/problem+json` format:


```json
{
  "type": "https://docs.vilna.io/errors/validation",
  "title": "Validation Error",
  "status": 422,
  "detail": "One or more fields are invalid.",
  "fields": [
    { "name": "address.value", "reason": "must be a valid blockchain address" }
  ]
}
```

The `fields` array pinpoints exactly which inputs failed and why.

## Further reading

CAIP Standards
Full reference for CAIP-2, CAIP-10, and CAIP-19 identifiers

Authentication
API keys, webhook signatures, and security best practices

Integration Patterns
Common architectures built on these concepts

Platform API
Complete endpoint documentation

Management API
Workspace, project, and key management endpoints