# Get chain by ID
Source: https://developers.zerion.io/api-reference/chains/get-chain-by-id
/openapi-v1.yaml get /v1/chains/{chain_id}
This endpoint returns chain by unique chain identifier.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
# Get list of all chains
Source: https://developers.zerion.io/api-reference/chains/get-list-of-all-chains
/openapi-v1.yaml get /v1/chains/
This endpoint returns list of all chains supported by Zerion.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
# Get DApp by ID
Source: https://developers.zerion.io/api-reference/dapps/get-dapp-by-id
/openapi-v1.yaml get /v1/dapps/{dapp_id}
This endpoint returns single DApp by its unique identifier.
# Get list of DApps
Source: https://developers.zerion.io/api-reference/dapps/get-list-of-dapps
/openapi-v1.yaml get /v1/dapps
This endpoint returns list of DApps by using different parameters.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get a chart for a fungible asset
Source: https://developers.zerion.io/api-reference/fungibles/get-a-chart-for-a-fungible-asset
/openapi-v1.yaml get /v1/fungibles/{fungible_id}/charts/{chart_period}
This endpoint returns the chart for the fungible asset for a selected period
# Get a chart for a fungible asset by implementation
Source: https://developers.zerion.io/api-reference/fungibles/get-a-chart-for-a-fungible-asset-by-implementation
/openapi-v1.yaml get /v1/fungibles/by-implementation/charts/{chart_period}
This endpoint returns the chart for a fungible asset for a selected period, identified by its implementation.
The implementation is a chain:address pair (e.g., "ethereum:0xa5a4214bb5f00c86b7969b7dc007302e4f6f05d6").
# Get fungible asset by ID
Source: https://developers.zerion.io/api-reference/fungibles/get-fungible-asset-by-id
/openapi-v1.yaml get /v1/fungibles/{fungible_id}
This endpoint returns a fungible asset by unique identifier
# Get fungible asset by implementation
Source: https://developers.zerion.io/api-reference/fungibles/get-fungible-asset-by-implementation
/openapi-v1.yaml get /v1/fungibles/by-implementation
This endpoint returns a fungible asset by its implementation.
The implementation is a `chain` (for base asset) or `chain:address` pair (e.g., "ethereum", ethereum:0xa5a4214bb5f00c86b7969b7dc007302e4f6f05d6").
# Get list of fungible assets
Source: https://developers.zerion.io/api-reference/fungibles/get-list-of-fungible-assets
/openapi-v1.yaml get /v1/fungibles/
This endpoint returns a paginated list of fungible assets supported by Zerion. It also provides the ability to search for fungibles.
If no fungible assets are found for given filters, the empty list with 200 status is returned.
> NOTE: This endpoint supports a lot of filters, sorting, and pagination parameters. Ensure your request URL length is within a safe range for your platform. Usually, 2000 characters are the safe limit in virtually any combination of client and server software.
> NOTE: The `filter[implementation_address]` parameter ignores `filter[search_query]`. It may be changed in the future.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get list of all available gas prices
Source: https://developers.zerion.io/api-reference/gas/get-list-of-all-available-gas-prices
/openapi-v1.yaml get /v1/gas-prices/
This endpoint provides real-time information on the current gas prices across all supported blockchain networks. Gas prices play a crucial role in the speed and cost of executing transactions on a blockchain, and fluctuate frequently based on network demand and usage. By using this endpoint, developers can stay up-to-date with the latest gas prices and adjust their application's transaction parameters accordingly to ensure optimal speed and cost efficiency.
# Get list of NFTs
Source: https://developers.zerion.io/api-reference/nfts/get-list-of-nfts
/openapi-v1.yaml get /v1/nfts/
This endpoint returns list of NFTs by using different parameters.
It returns NFTs of both types - ERC721 and ERC1155.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get single NFT by ID
Source: https://developers.zerion.io/api-reference/nfts/get-single-nft-by-id
/openapi-v1.yaml get /v1/nfts/{nft_id}
This endpoint returns single NFT by its unique identifier.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
# Count wallets within subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/count-wallets-within-subscription
/openapi-v1.yaml get /v1/tx-subscriptions/{subscription_id}/wallets/count
This endpoint returns the count of wallets within a specific subscription by subscription ID.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Create subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/create-subscription
/openapi-v1.yaml post /v1/tx-subscriptions/
This endpoint subscribes to new transactions associated with the wallets.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
### Use Case
The main use case for the webhooks system is to send notifications, similar to push notifications in the Zerion App.
### Setup Callback URL
If you want to use this endpoint to test how it works, you might use your dev key to start. It has limits: one subscription & maximum 5 wallets per subscription.
You may use callback URL from webhook.site to start from. If want use your custom - contact us at api@zerion.io, and we will whitelist your URL.
If you want to use this endpoint in your production environment, you should contact us and provide the following details:
- Your email associated with the API key
- The URL that you prefer using as the callback (or host).
After we've whitelisted your callback URL (or host), you may start using this endpoint.
### Note
- **Subscription Validity**: Every subscription is valid for unlimited amount of time for production key, and one week for `dev` keys.
- **Transaction Prices**: Prices are not attached to webhook notifications and will always be `null`. Prices are added to transactions in the backend after some time. To get prices, query the transactions endpoint by hash.
- **Delivery Guarantees**: Webhook delivery is not guaranteed. If delivery fails three times, no further attempts will be made.
- **Order of Dispatch**: The order of webhook dispatch is not guaranteed and may not correspond to the order of transactions occurring on the blockchain.
### Callback Format and Signature Verification
Approved clients will receive notifications via POST requests to their provided URL. These notifications will include a signed notification object in the body (specified below in the `Callback` section) and a signature in the headers.
Clients should verify the signature provided in the headers of the webhook request to ensure the authenticity of the data. The following headers will be included:
- `X-Signature`: The signature of the request.
- `X-Timestamp`: The timestamp of the request.
- `X-Certificate-URL`: The URL to download the public certificate used to verify the signature.
**To verify the signature:**
1. Concatenate the `X-Timestamp` header value, the request body, and a newline character: `$timestamp + "\n" + $request.body + "\n"`
2. Use the public certificate downloaded from the `X-Certificate-URL` header to verify the signature in the `X-Signature` header.
Example code in go for message verification:
```go
package signature
import (
"crypto"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"github.com/stretchr/testify/assert"
"testing"
)
// FetchCertificate fetches the certificate from the given URL
func FetchCertificate() (*x509.Certificate, error) {
certBytes := certificate()
block, _ := pem.Decode(certBytes)
if block == nil || block.Type != "CERTIFICATE" {
return nil, errors.New("failed to decode PEM block containing the certificate")
}
return x509.ParseCertificate(block.Bytes)
}
func certificate() []byte {
return []byte(`-----BEGIN CERTIFICATE-----
MIIDMTCCAhmgAwIBAgIUDd3dFMswamyJ5A1bqF0nzS8v2wgwDQYJKoZIhvcNAQEL
BQAwQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC1plcmlvbiBJbmMuMRwwGgYJKoZI
hvcNAQkBFg1hcGlAemVyaW9uLmlvMB4XDTI0MDYyNzE1MzUzM1oXDTI1MDYyNzE1
MzUzM1owQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC1plcmlvbiBJbmMuMRwwGgYJ
KoZIhvcNAQkBFg1hcGlAemVyaW9uLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAwcPVCPLDhS9dLA8s5J6GJ3t0+jWuUCFwI+q6c03xZnhCaz45FepN
MTiApbvPw1Zm8F8JQB4BRp/F5anokNcDSl/qmNtj3M/z/FrsVvGnSH2FOkZu9TLU
LTW5i8Q0LAYrpgiBHrTa2qrRXd2DiMrEs3QZVoylFYc9QIGet3SULPrlSsYEKxfB
iBZDoFw619NnV6/kBO8FS34Lc+WH5SNNHNnItRrxMv4DMAFyFajSn1IwV6LSWSNK
aPJHCzP/Omu95550HQKcXaJYNE/d99NrcLaFI2fCuEVd00nApFo5knKs0FiXpGca
l3cLOQG5SCOzUOjQb6X5CynEV+0QiyYxDwIDAQABoyEwHzAdBgNVHQ4EFgQUVL4m
u0PcI4nJGUS8syLi5DNL44YwDQYJKoZIhvcNAQELBQADggEBAKaA1oqW0D6KxvIp
IZxWf02XK/YFYwxKV55Vas0VWlzNemE2IjlIj0tknZt0EiM9um2FC27U9n3u0ApS
UDrk96dQ+/RY3T3fiuXysa3ZL05OpreRk0aPuFU9rB4iLTgFiv1G/X5XXJ8O7OQb
48u0vQnYXjT/nt72TMUoakjZ68QsP64FkG8mcK62Tg+FVWB9YWTFc0wOjsOt9RzJ
muKCQ7qx7L1GhkxKX4ZhrYItsH1DzXjeP5aniZgLBSPbxt01tUrSjOGN5CLOpdG8
iOnAFP+Nz8S0h2C7hppOHgC+uxY285UrzAZQoMbCREMV+0Mq/aqdF1B6qoKGNGqL
kFbUhvo=
-----END CERTIFICATE-----
`)
}
func VerifySignature(cert *x509.Certificate, message, signature string) error {
pubKey := cert.PublicKey.(*rsa.PublicKey)
hashed := sha256.Sum256([]byte(message))
sigBytes, err := base64.StdEncoding.DecodeString(signature)
if err != nil {
return err
}
return rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, hashed[:], sigBytes)
}
func TestVerifySignature(t *testing.T) {
// Example usage
x509Cert, err := FetchCertificate()
assert.NoError(t, err)
xTimestamp := "2024-07-31T00:17:36Z"
xSignature := "t65gdR8z3NGh/OQRPzGMFmw36JhDNvOe6LxL6K2hCd3SdYQoTGr76dAy1CpsX2G8XVOIYUIctUQvgICQvtDctVjkRZmXuQDvXHOmiJE0ZknORgjVLFoo5JRYKvwt3EPp6SMN7RtedIX17rH1s2Vp3GRQWSjzN7C/cNgInhCQOP0UDjYlaeNT/yW4B2Qt4uY01yK0YhvQJaFHN+NNr7DZAt4FJuDppItqjaYbHTaFNqLlpI1IX7YvQWVhEYTJY6M4T9IdcGYPJKDljckjvmj9mDHZeh/Y6w8eXjLziMSFvlhJeSn1kBIR3nS7lTcwFNv1CPxD3MM7VB++te3mBbFubg=="
messageBody := `{"data":{"attributes":{"timestamp":"2024-07-31T00:17:36.661896043Z"},"id":"15daee90-5028-4b4c-bd49-b4d43fa1a89e","type":"callback"},"included":[{"attributes":{"application_metadata":{"contract_address":"0x8286d601a0ed6cf75e067e0614f73a5b9f024151","method":{"id":"0x7859bb8d","name":""}},"approvals":[],"fee":{"fungible_info":{"flags":{"verified":true},"icon":{"url":"https://cdn.zerion.io/eth.png"},"implementations":[{"address":"","chain_id":"redstone","decimals":18},{"address":"","chain_id":"polygon-zkevm","decimals":18},{"address":"","chain_id":"optimism","decimals":18},{"address":"","chain_id":"zksync-era","decimals":18},{"address":"","chain_id":"mode","decimals":18},{"address":"","chain_id":"base","decimals":18},{"address":"","chain_id":"ethereum","decimals":18},{"address":"","chain_id":"aurora","decimals":18},{"address":"","chain_id":"scroll","decimals":18},{"address":"","chain_id":"rari","decimals":18},{"address":"","chain_id":"astar-zkevm","decimals":18},{"address":"","chain_id":"arbitrum","decimals":18},{"address":"","chain_id":"zora","decimals":18},{"address":"","chain_id":"blast","decimals":18},{"address":"","chain_id":"linea","decimals":18},{"address":"","chain_id":"manta-pacific","decimals":18}],"name":"Ethereum","symbol":"ETH"},"price":null,"quantity":{"decimals":18,"float":0.0000016785001958,"int":"1678500195825","numeric":"0.000001678500195825"},"value":null},"flags":{"is_trash":false},"hash":"0xbbcfb0ac5e466ded168794a162da334634fee3f95adfdb55392999f91b4c6d41","mined_at":"2024-07-31T00:17:35Z","mined_at_block":7490818,"nonce":250,"operation_type":"execute","sent_from":"0xfc0f1b3fb88c5ab19e77a6f7d4d637272e71e684","sent_to":"0x8286d601a0ed6cf75e067e0614f73a5b9f024151","status":"confirmed","transfers":[]},"id":"a65b2541c58a5908a7333480f0ac6792","relationships":{"chain":{"id":"linea","type":"chains"},"dapp":{"id":"","type":"dapps"}},"type":"transactions"}]}`
message := xTimestamp + "\n" + messageBody + "\n"
err = VerifySignature(x509Cert, message, xSignature)
assert.NoError(t, err)
}
```
# Delete subscription by ID
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/delete-subscription-by-id
/openapi-v1.yaml delete /v1/tx-subscriptions/{subscription_id}
This endpoint deletes existing subscription
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Disable a specific subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/disable-a-specific-subscription
/openapi-v1.yaml patch /v1/tx-subscriptions/{subscription_id}/disable
This endpoint sets the status of a specific subscription to "disabled".
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. This ensures flexibility and future-proofing against ID format changes.
# Enable a specific subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/enable-a-specific-subscription
/openapi-v1.yaml patch /v1/tx-subscriptions/{subscription_id}/enable
This endpoint sets the status of a specific subscription to "enabled".
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. This ensures flexibility and future-proofing against ID format changes.
# Find subscription by ID
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/find-subscription-by-id
/openapi-v1.yaml get /v1/tx-subscriptions/{subscription_id}
This endpoint by ID returns subscription to new transactions associated with the wallets and chains.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Find subscriptions
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/find-subscriptions
/openapi-v1.yaml get /v1/tx-subscriptions/
This endpoint finds subscriptions to new transactions associated with the wallets and chains. Currently response is limited to 1000 subscriptions in the response.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Find wallets within subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/find-wallets-within-subscription
/openapi-v1.yaml get /v1/tx-subscriptions/{subscription_id}/wallets
This endpoint by subscription ID returns wallets within specific subscription.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Patch wallets within subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/patch-wallets-within-subscription
/openapi-v1.yaml patch /v1/tx-subscriptions/{subscription_id}/wallets
This endpoint works by subscription ID. It patches wallets list within specific subscription.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Replace wallets within subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/replace-wallets-within-subscription
/openapi-v1.yaml put /v1/tx-subscriptions/{subscription_id}/wallets
This endpoint works by subscription ID. It replaces wallets list within specific subscription.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Update callback URL within subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/update-callback-url-within-subscription
/openapi-v1.yaml patch /v1/tx-subscriptions/{subscription_id}/callback_url
This endpoint updates the callback URL for a specific subscription.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Update chain IDs within subscription
Source: https://developers.zerion.io/api-reference/subscriptions-to-transactions/update-chain-ids-within-subscription
/openapi-v1.yaml patch /v1/tx-subscriptions/{subscription_id}/chain_ids
This endpoint updates the list of chain IDs associated with a specific subscription.
> NOTE:
> - Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions.
> - The chain IDs provided will replace the existing chain IDs associated with the subscription.
# Get swap and bridge quotes
Source: https://developers.zerion.io/api-reference/swap/get-swap-and-bridge-quotes
/openapi-v1.yaml get /v1/swap/quotes/
Returns quotes from multiple liquidity sources for a same-chain swap or a cross-chain bridge between two fungible assets. Supports EVM chains and Solana, including EVM ↔ Solana bridges.
Quotes are returned best-first: sorted in descending order by the fiat value of `output_amount_after_fees` (output amount minus network, protocol and bridge fees that are not already included in the rate). Quotes with the same score are tied-broken alphabetically by `liquidity_source.id`, so identical requests always return quotes in the same order.
The `input` and `output` parameters are objects encoded with bracket notation in the URL — the request is sent as a flat query string. For example:
```
GET /v1/swap/quotes/?currency=usd&input[chain_id]=base&input[fungible_id]=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&input[amount]=0.001&output[fungible_id]=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&from=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&to=0xd8da6bf26964af9d7eed9e03e53415d37aa96045
```
# List fungibles available for bridging
Source: https://developers.zerion.io/api-reference/swap/list-fungibles-available-for-bridging
/openapi-v1.yaml get /v1/swap/fungibles/
Returns the list of tokens available for bridging between two chains. Use this to populate a token picker UI. Only relevant for cross-chain swaps, same-chain swaps don't require this step.
# Get wallet set balance chart
Source: https://developers.zerion.io/api-reference/wallet-sets/get-wallet-set-balance-chart
/openapi-v1.yaml get /v1/wallet-sets/charts/{chart_period}
This endpoint returns a portfolio balance chart for a wallet set.
A wallet set is represented by an EVM address, a Solana address, or both. At least one address must be provided.
This is over a specified time period, based on the provided start and end timestamps.
Results can be filtered by blockchain and asset type, offering flexible and detailed visualizations of wallet set performance, similar to what you see in the Zerion interface.
Note: We do not support historical protocol positions data.
# Get wallet set fungible positions
Source: https://developers.zerion.io/api-reference/wallet-sets/get-wallet-set-fungible-positions
/openapi-v1.yaml get /v1/wallet-sets/positions/
This endpoint returns a list of wallet set positions.
A wallet set is represented by an EVM address, a Solana address, or both. At least one address must be provided.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
**Understanding Liquidity Pool Positions:**
Liquidity pools (Uniswap, Curve, Balancer, etc.) return **multiple positions** - one for each token in the pool. Positions belonging to the same pool share the same `group_id` value in attributes.
For example, a Uniswap V2 USDC/WETH pool returns two positions:
- Position 1: WETH token, `group_id="820ee2f1ca8ccb716f6beb5e450908a028be890ec44aba87c739b416ef41e197"`, `fungible_info.symbol="WETH"`
- Position 2: USDC token, `group_id="820ee2f1ca8ccb716f6beb5e450908a028be890ec44aba87c739b416ef41e197"`, `fungible_info.symbol="USDC"`
To display all tokens in a liquidity pool together, group positions by their `group_id` attribute.
**Temporary limitations for Solana addresses:**
- Doesn't support protocol positions
> NOTE: Don't forget to stop retries after some reasonable period of time. If the `200` status is not returned within 2 minutes it most probably means that some unexpected error occurred and the client should stop the polling.
> NOTE: This endpoint supports a lot of filters, sorting and pagination parameters. Make sure that a request URL length is in a safe range for your platform. Usually, 2000 characters are the safe limit in virtually any combination of client and server software.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get wallet set PnL
Source: https://developers.zerion.io/api-reference/wallet-sets/get-wallet-set-pnl
/openapi-v1.yaml get /v1/wallet-sets/pnl
This endpoint returns the Profit and Loss (PnL) details of a wallet set.
A wallet set is represented by an EVM address, a Solana address, or both. At least one address must be provided.
This includes Unrealized PnL, Realized PnL, Net Invested amounts and filters for asset categories like Non Fungible Tokens (NFTs).
It uses the FIFO (First In, First Out) standard for calculations, providing accurate insights into wallet set performance.
Ideal for tracking and analyzing financial outcomes of wallet activity across multiple addresses.
The very first request for a wallet set might result in a 503 which should be retried later.
Wallet sets with over 1 million transactions are not supported.
# Get wallet set portfolio
Source: https://developers.zerion.io/api-reference/wallet-sets/get-wallet-set-portfolio
/openapi-v1.yaml get /v1/wallet-sets/portfolio
This endpoint returns a wallet set's portfolio overview.
A wallet set is represented by an EVM address, a Solana address, or both. At least one address must be provided.
**Temporary limitations for Solana addresses:**
- Doesn't support protocol positions
> NOTE: Don't forget to stop retries after some reasonable period of time. If the `200` status is not returned within 2 minutes it most probably means that some unexpected error occurred and the client should stop the polling.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get wallet set transactions
Source: https://developers.zerion.io/api-reference/wallet-sets/get-wallet-set-transactions
/openapi-v1.yaml get /v1/wallet-sets/transactions/
This endpoint returns a list of transactions associated with the wallet set.
A wallet set is represented by an EVM address, a Solana address, or both. At least one address must be provided.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
**Temporary limitations for Solana addresses:**
- Doesn't support NFT transactions
> NOTE: This endpoint supports a lot of filters, sorting, and pagination parameters. Make sure that your request URL length is safe for your platform. Usually, 2000 characters are the safe limit in virtually any combination of client and server software.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get wallet balance chart
Source: https://developers.zerion.io/api-reference/wallets/get-wallet-balance-chart
/openapi-v1.yaml get /v1/wallets/{address}/charts/{chart_period}
This endpoint returns a portfolio balance chart for a wallet.
This is over a specified time period, based on the provided start and end timestamps.
Results can be filtered by blockchain and asset type, offering flexible and detailed visualizations of wallet performance, similar to what you see in the Zerion interface.
Note: We do not support historical protocol positions data.
# Get wallet fungible positions
Source: https://developers.zerion.io/api-reference/wallets/get-wallet-fungible-positions
/openapi-v1.yaml get /v1/wallets/{address}/positions/
This endpoint returns a list of wallet positions.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
**Understanding Liquidity Pool Positions:**
Liquidity pools (Uniswap, Curve, Balancer, etc.) return **multiple positions** - one for each token in the pool. Positions belonging to the same pool share the same `group_id` value in attributes.
For example, a Uniswap V2 USDC/WETH pool returns two positions:
- Position 1: WETH token, `group_id="820ee2f1ca8ccb716f6beb5e450908a028be890ec44aba87c739b416ef41e197"`, `fungible_info.symbol="WETH"`
- Position 2: USDC token, `group_id="820ee2f1ca8ccb716f6beb5e450908a028be890ec44aba87c739b416ef41e197"`, `fungible_info.symbol="USDC"`
To display all tokens in a liquidity pool together, group positions by their `group_id` attribute.
**Temporary limitations for Solana addresses:**
- Doesn't support protocol positions
> NOTE: Don't forget to stop retries after some reasonable period of time. If the `200` status is not returned within 2 minutes it most probably means that some unexpected error occurred and the client should stop the polling.
> NOTE: This endpoint supports a lot of filters, sorting and pagination parameters. Make sure that a request URL length is in a safe range for your platform. Usually, 2000 characters are the safe limit in virtually any combination of client and server software.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get wallet NFT collections
Source: https://developers.zerion.io/api-reference/wallets/get-wallet-nft-collections
/openapi-v1.yaml get /v1/wallets/{address}/nft-collections/
This endpoint returns a list of the NFT collections held by a specific wallet.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
If the wallet address has not been previously added, this endpoint may return a `202` status code. This indicates that the wallet's collections are not yet available, but will be in the near future. In this case, the client should periodically request this endpoint until a `200` status code is returned.
> NOTE: It is important to stop retrying after a reasonable period of time. If a `200` status code is not returned within 2 minutes, it is likely that an unexpected error has occurred, and the client should stop polling.
> NOTE: This endpoint provides support for filters, sorting. Ensure that the length of the request URL falls within a safe range for your platform. Typically, a length of 2000 characters is a safe limit for most combinations of client and server software.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get wallet NFT portfolio
Source: https://developers.zerion.io/api-reference/wallets/get-wallet-nft-portfolio
/openapi-v1.yaml get /v1/wallets/{address}/nft-portfolio
This endpoint returns the NFT portfolio overview of a web3 wallet.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
If the address was not added before it is possible that this endpoint will return `202` status. It means that portfolio for the wallet is not prepared yet, but will be available soon. In that case the client have to request this endpoint periodically, while `200` status wasn't returned.
> NOTE: Don't forget to stop retries after some reasonable period of time. If the `200` status is not returned within 2 minutes it most probably means that some unexpected error occurred and the client should stop the polling.
# Get wallet NFT positions
Source: https://developers.zerion.io/api-reference/wallets/get-wallet-nft-positions
/openapi-v1.yaml get /v1/wallets/{address}/nft-positions/
This endpoint returns a list of the NFT positions held by a specific wallet.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
If the wallet address has not been previously added, this endpoint may return a `202` status code. This indicates that the wallet's positions are not yet available, but will be in the near future. In this case, the client should periodically request this endpoint until a `200` status code is returned.
> NOTE: It is important to stop retrying after a reasonable period of time. If a `200` status code is not returned within 2 minutes, it is likely that an unexpected error has occurred and the client should stop polling.
> NOTE: This endpoint provides support for filters, sorting, and pagination parameters. Ensure that the length of the request URL falls within a safe range for your platform. Typically, a length of 2000 characters is a safe limit for most combinations of client and server software.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get wallet PnL
Source: https://developers.zerion.io/api-reference/wallets/get-wallet-pnl
/openapi-v1.yaml get /v1/wallets/{address}/pnl
This endpoint returns the Profit and Loss (PnL) details of a web3 wallet.
This includes Unrealized PnL, Realized PnL, Net Invested amounts and filters for asset categories like Non Fungible Tokens (NFTs).
It uses the FIFO (First In, First Out) standard for calculations, providing accurate insights into wallet performance.
Ideal for tracking and analyzing financial outcomes of wallet activity.
The very first request for a wallet might result in a 503 which should be retried later.
Wallets with over 1 million transactions are not supported.
# Get wallet portfolio
Source: https://developers.zerion.io/api-reference/wallets/get-wallet-portfolio
/openapi-v1.yaml get /v1/wallets/{address}/portfolio
This endpoint returns the portfolio overview of a web3 wallet.
**Temporary limitations for Solana addresses:**
- Doesn't support protocol positions
> NOTE: Don't forget to stop retries after some reasonable period of time. If the `200` status is not returned within 2 minutes it most probably means that some unexpected error occurred and the client should stop the polling.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Get wallet transactions
Source: https://developers.zerion.io/api-reference/wallets/get-wallet-transactions
/openapi-v1.yaml get /v1/wallets/{address}/transactions/
This endpoint returns a list of transactions associated with the wallet.
This endpoint supports testnets. To get data for testnets use `X-Env` header.
**Temporary limitations for Solana addresses:**
- Doesn't support NFT transactions
> NOTE: This endpoint supports a lot of filters, sorting, and pagination parameters. Make sure that your request URL length is safe for your platform. Usually, 2000 characters are the safe limit in virtually any combination of client and server software.
> NOTE: Consider all IDs as abstract strings, without making any assumptions about their format or relying on such assumptions. There is a non-zero probability that IDs may change in the future, and this should not result in any breaking changes.
# Authentication
Source: https://developers.zerion.io/authentication
How to authenticate with the Zerion API
The Zerion API supports three ways to authenticate a request:
| Method | Best for | How it works |
| ------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| **API key** | Apps and services with steady traffic | HTTP Basic Auth with a key from the [Dashboard](https://dashboard.zerion.io). Subject to rate limits. |
| **[x402](/build-with-ai/x402)** | AI agents and per-call workloads | Pay USDC on Base or Solana per request. No API key, no rate limits. |
| **[MPP](/build-with-ai/mpp)** | AI agents and per-call workloads | Pay USDC on Tempo per request. No API key, no rate limits. |
The rest of this page covers the API key flow. For pay-per-request flows, see the dedicated [x402](/build-with-ai/x402) and [MPP](/build-with-ai/mpp) pages.
## API key
The Zerion API uses [HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#basic_authentication_scheme). You can get your API key from the [Dashboard](https://dashboard.zerion.io).
### Try it from the docs
Every API reference page has an interactive playground. Click **Try it**, paste your API key in the **Username** field, leave **Password** empty, and hit **Send** to make a live request.
### Using the API from your code
When calling the API from code, append a colon to your API key (`your_api_key:`), Base64-encode it, and pass it in the `Authorization` header:
```
Authorization: Basic BASE64_ENCODED_KEY
```
Go to the [Dashboard](https://dashboard.zerion.io) Get Started section for ready-to-use code snippets with your API key pre-filled.
```bash cURL theme={null}
# Transform your API key for Basic Auth
API_KEY_TRANSFORMED=$(echo -n "YOUR_API_KEY:" | base64)
# Make the request
curl -X GET "https://api.zerion.io/v1/wallets/0x42b9df65b219b3dd36ff330a4dd8f327a6ada990/portfolio" \
-H "Authorization: Basic $API_KEY_TRANSFORMED" \
-H "accept: application/json"
```
```javascript JavaScript theme={null}
// Transform your API key for Basic Auth
const apiKey = 'YOUR_API_KEY';
const apiKeyTransformed = btoa(apiKey + ':');
// Make the request
const response = await fetch(
'https://api.zerion.io/v1/wallets/0x42b9df65b219b3dd36ff330a4dd8f327a6ada990/portfolio',
{
headers: {
'Authorization': `Basic ${apiKeyTransformed}`,
'accept': 'application/json'
}
}
);
const data = await response.json();
console.log(data);
```
```python Python theme={null}
import requests
import base64
# Transform your API key for Basic Auth
api_key = 'YOUR_API_KEY'
api_key_transformed = base64.b64encode(f'{api_key}:'.encode()).decode()
# Make the request
response = requests.get(
'https://api.zerion.io/v1/wallets/0x42b9df65b219b3dd36ff330a4dd8f327a6ada990/portfolio',
headers={
'Authorization': f'Basic {api_key_transformed}',
'accept': 'application/json'
}
)
data = response.json()
print(data)
```
```go Go theme={null}
import (
"encoding/base64"
"net/http"
)
// Transform your API key for Basic Auth
apiKey := "YOUR_API_KEY"
apiKeyTransformed := base64.StdEncoding.EncodeToString([]byte(apiKey + ":"))
// Make the request
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://api.zerion.io/v1/wallets/0x42b9df65b219b3dd36ff330a4dd8f327a6ada990/portfolio", nil)
req.Header.Set("Authorization", "Basic " + apiKeyTransformed)
req.Header.Set("accept", "application/json")
resp, _ := client.Do(req)
defer resp.Body.Close()
```
### Security best practices
Never expose your API key in client-side code or public repositories.
* Store your API key in environment variables
* Make API requests from server-side code
* Rotate your key immediately if it's ever compromised
* Use separate keys for development and production
## Pay-per-request: x402 and MPP
Both x402 and MPP let you call the Zerion API by paying a small USDC fee per request instead of presenting an API key. They're a better fit than API keys when:
* You're building an AI agent or automated pipeline that shouldn't manage long-lived credentials
* Traffic is bursty or unpredictable and you don't want to size a rate-limited plan
* You want usage-based cost accounting at the request level
The two protocols differ only in which chain they settle on:
* **[x402](/build-with-ai/x402)** ([Coinbase's open protocol](https://github.com/coinbase/x402)) — settles in USDC on **Base** or **Solana**. Uses the `PAYMENT-SIGNATURE` request header.
* **[MPP](/build-with-ai/mpp)** ([Machine Payments Protocol](https://mpp.dev)) — settles in USDC on **Tempo**. Uses the `Authorization: Payment` request header.
Both cover the same set of endpoints as API-key auth and accept the same parameters. Pick whichever chain your wallet already holds USDC on. The [Zerion CLI](/build-with-ai/zerion-cli) supports both via `--x402` / `--mpp` flags.
# MCP
Source: https://developers.zerion.io/build-with-ai/mcp
Connect your AI tools to the Zerion API docs via Model Context Protocol.
The Zerion API docs are available as a Model Context Protocol (MCP) server. Once connected, your AI tool can search our full documentation and OpenAPI spec while generating code — no copy-pasting needed.
## Connect via MCP
Run this in your terminal:
```bash theme={null}
claude mcp add --transport http zerion-api https://developers.zerion.io/mcp
```
The Zerion docs will be available as a tool in all Claude Code sessions.
Open the command palette (`Cmd+Shift+P`) → "MCP: Edit Config", then add:
```json theme={null}
{
"mcpServers": {
"zerion-api": {
"url": "https://developers.zerion.io/mcp"
}
}
}
```
Create `.vscode/mcp.json` in your project:
```json theme={null}
{
"servers": {
"zerion-api": {
"type": "http",
"url": "https://developers.zerion.io/mcp"
}
}
}
```
1. Go to Claude settings → **Connectors**
2. Select **Add custom connector**
3. Name: `Zerion API`, URL: `https://developers.zerion.io/mcp`
4. Use the attachments button (+) in any chat to access it
## What you can ask
Once connected, you can ask your AI assistant things like:
* *"How do I get a wallet's token positions on Ethereum?"*
* *"Write a Python script that fetches transaction history and filters for trades"*
* *"What filters are available on the positions endpoint?"*
The AI will search the Zerion docs in real-time to give you accurate, up-to-date answers.
## Open in AI assistants
You can also open any documentation page directly in an AI chat for quick questions:
Paste any docs page URL into Claude for API questions and code generation.
Use ChatGPT to explore endpoints and generate integration code.
For the best experience, use the MCP integration instead of copy-pasting. It gives the AI access to the full docs and API spec, not just one page at a time.
# MPP Payments
Source: https://developers.zerion.io/build-with-ai/mpp
Access the Zerion API per-request using USDC on Tempo — no API key required.
MPP ([Machine Payments Protocol](https://mpp.dev)) is an open protocol for pay-per-request HTTP access. Instead of an API key, you pay a small amount of USDC on Tempo for each request — ideal for AI agents that need onchain data without managing subscriptions or key rotation.
This is an alternative authorization method for the same Zerion API. Endpoints, JSON:API responses, query parameters, and filters all behave exactly as in the rest of the docs — only the way you prove access changes.
Zerion also supports [x402](./x402), a sibling protocol that settles on Base or Solana. See [Authentication](/authentication) for an overview of all access methods.
## Quickstart with the Zerion CLI
The easiest way to use MPP is with the [Zerion CLI](./zerion-cli), which handles the payment handshake, wallet signing, and retries automatically.
Set an EVM private key for a wallet that holds USDC on Tempo, then make a request with `--mpp`:
```bash theme={null}
export WALLET_PRIVATE_KEY="0x..."
zerion-cli wallet portfolio 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --mpp
```
Set `ZERION_MPP=true` to enable MPP globally for analytics commands instead of passing `--mpp` on every call. If you already use `WALLET_PRIVATE_KEY` for x402, the same key works for MPP — or set `TEMPO_PRIVATE_KEY` to use a different wallet for Tempo.
## Direct integration
If you're not using the CLI, use one of the [official MPP SDKs](https://mpp.dev/sdk) (TypeScript, Python, Go, Rust) to handle payment construction and retries. You'll need a wallet with USDC on Tempo and its EVM private key.
## Example
```ts theme={null}
import { privateKeyToAccount } from 'viem/accounts'
import { Mppx, tempo } from 'mppx/client'
Mppx.create({
methods: [tempo({ account: privateKeyToAccount(process.env.WALLET_PRIVATE_KEY) })],
})
// Global fetch now handles 402 automatically
const res = await fetch(
'https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/portfolio'
)
const data = await res.json()
```
## How it works
```
Client Zerion API
| |
| 1. GET /v1/wallets/... |
| --------------------------> |
| |
| 2. 402 Payment Required |
| <-------------------------- |
| WWW-Authenticate: |
| Payment |
| |
| 3. GET /v1/wallets/... |
| Authorization: |
| Payment |
| --------------------------> |
| |
| 4. 200 OK |
| Payment-Receipt: ... |
| <-------------------------- |
| |
```
1. Client sends a request to an API endpoint
2. Server returns `402` with a `WWW-Authenticate: Payment` challenge describing where and how much to pay
3. Client signs a USDC transfer on Tempo and retries with an `Authorization: Payment` header
4. Zerion verifies the credential with the MPP facilitator and returns the response
## Rate limits
None — pay per request, no per-second or monthly quota.
## Error handling
* `402 Payment required` — no or invalid payment credential. Inspect the `WWW-Authenticate: Payment` response header for a fresh challenge and retry.
* `402 MPP payment rejected` — the facilitator rejected the credential. The `detail` field contains the reason (e.g. insufficient funds, expired authorization).
# Overview
Source: https://developers.zerion.io/build-with-ai/overview
Connect AI agents and assistants to onchain data through the Zerion API.
Give your AI agents access to wallet portfolios, token data, transactions, and DeFi positions across all supported chains. Zerion provides multiple ways to integrate depending on your setup.
Give AI agents access to onchain data via shell commands — no API integration needed.
Let AI agents pay for API access per-request using stablecoins — no API keys needed.
Connect AI tools like Claude Code, Cursor, and VS Code to the Zerion docs and OpenAPI spec via Model Context Protocol.
# x402 Payments
Source: https://developers.zerion.io/build-with-ai/x402
Access the Zerion API per-request using USDC on Base or Solana — no API key required.
x402 is [Coinbase's open protocol](https://github.com/coinbase/x402) for pay-per-request HTTP access. Instead of an API key, you pay a small amount of USDC on Base or Solana for each request — ideal for AI agents that need onchain data without managing subscriptions or key rotation.
This is an alternative authorization method for the same Zerion API. Endpoints, JSON:API responses, query parameters, and filters all behave exactly as in the rest of the docs — only the way you prove access changes.
Zerion also supports [MPP](./mpp), a sibling protocol that settles on Tempo. See [Authentication](/authentication) for an overview of all access methods.
## Quickstart with the Zerion CLI
The easiest way to use x402 is with the [Zerion CLI](./zerion-cli), which handles the payment handshake, wallet signing, and retries automatically.
Set the private key of the wallet that holds USDC, then make a request with `--x402`:
```bash theme={null}
export WALLET_PRIVATE_KEY="0x..."
zerion-cli wallet portfolio 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --x402
```
```bash theme={null}
export SOLANA_PRIVATE_KEY=""
export ZERION_X402_PREFER_SOLANA=true
zerion-cli wallet portfolio 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --x402
```
Set `ZERION_X402=true` to enable x402 globally for analytics commands instead of passing `--x402` on every call.
## Direct integration
If you're not using the CLI, use the [Coinbase x402 SDK](https://github.com/coinbase/x402) (Go, TypeScript, Python) to handle payment construction and retries. You'll need a wallet with USDC on Base or Solana and its private key.
## Example
```ts theme={null}
import { wrapFetchWithPayment, x402Client } from '@x402/fetch'
import { registerExactEvmScheme } from '@x402/evm/exact/client'
import { privateKeyToAccount } from 'viem/accounts'
const client = new x402Client()
registerExactEvmScheme(client, {
signer: privateKeyToAccount(process.env.WALLET_PRIVATE_KEY),
})
const fetchWithPayment = wrapFetchWithPayment(fetch, client)
const res = await fetchWithPayment(
'https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/portfolio'
)
const data = await res.json()
```
## How it works
```
Client Zerion API
| |
| 1. GET /v1/wallets/... |
| --------------------------> |
| |
| 2. 402 Payment Required |
| <-------------------------- |
| PAYMENT-REQUIRED: |
| |
| |
| 3. GET /v1/wallets/... |
| PAYMENT-SIGNATURE: |
| |
| --------------------------> |
| |
| 4. 200 OK |
| <-------------------------- |
| |
```
1. Client sends a request to an API endpoint
2. Server returns `402` with a `PAYMENT-REQUIRED` header describing where and how much to pay
3. Client signs a USDC transfer and retries with a `PAYMENT-SIGNATURE` header
4. Zerion settles the payment via the Coinbase Developer Platform and returns the response
## Rate limits
None — pay per request, no per-second or monthly quota.
## Error handling
* `402 Payment required` — no or invalid payment signature. Inspect the `PAYMENT-REQUIRED` response header for a fresh challenge and retry.
* `402 x402 payment rejected` — the facilitator rejected the signature. The `detail` field contains the reason.
* `402 x402 payment settlement failed` — the signature was valid but on-chain settlement failed.
See the [Coinbase x402 troubleshooting docs](https://docs.cdp.coinbase.com/x402/support/troubleshooting#common-errors) for more.
# Skill + CLI
Source: https://developers.zerion.io/build-with-ai/zerion-cli
CLI for Zerion Wallet — analyze wallets, sign, swap, and bridge on-chain with agent-managed wallets across EVM chains and Solana, all from the command line. Plus agent skills that ship across every major AI coding agent.
The Zerion CLI is an open-source tool that wraps the Zerion API and a local encrypted wallet vault. The same binary powers both humans and AI agents — any agent that can run shell commands can analyze wallets, sign messages, and execute swaps without writing API integration code. Wallet management is built on the [Open Wallet Standard](https://github.com/open-wallet-standard/core).
Six agent skills ship alongside the CLI for AI coding agents (Claude Code, Cursor, Windsurf, Codex, Gemini, OpenCode, and any [agentskills.io](https://agentskills.io) host).
**Repository:** [github.com/zeriontech/zerion-ai](https://github.com/zeriontech/zerion-ai) — CLI and skills ship from the same repo.
**Alpha Preview** — The CLI is under active development. Commands, flags, and output formats may change between releases. Don't depend on current behavior in production workflows.
## Installation
One-shot setup — installs the CLI globally, configures your API key, and adds skills across all detected coding agents:
```bash theme={null}
npx -y zerion-cli init -y --browser
```
* `-y` runs setup non-interactively
* `--browser` opens [dashboard.zerion.io](https://dashboard.zerion.io) so you can grab an API key and paste it back
* Skills install globally to every detected AI coding agent
Or install the CLI binary on its own:
```bash theme={null}
npm install -g zerion-cli
```
Requires Node.js 20 or later.
## Authentication
Three options. The CLI auto-detects which is active.
### API key (recommended)
Get a free key at [dashboard.zerion.io](https://dashboard.zerion.io). Keys begin with `zk_`.
```bash theme={null}
export ZERION_API_KEY="zk_..."
```
Or persist it via config:
```bash theme={null}
zerion config set apiKey zk_...
```
Required for analysis and trading. Analysis can also use x402 / MPP pay-per-call.
### x402 pay-per-call
No API key needed. Pays \$0.01 USDC per request via the [x402 protocol](https://www.x402.org/). Supports EVM (Base) and Solana.
```bash theme={null}
export WALLET_PRIVATE_KEY="0x..." # EVM (Base) — 0x-prefixed hex
export WALLET_PRIVATE_KEY="5C1y..." # Solana — base58 keypair
zerion analyze 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --x402
```
Enable globally:
```bash theme={null}
export ZERION_X402=true
```
Both chains simultaneously:
```bash theme={null}
export EVM_PRIVATE_KEY="0x..."
export SOLANA_PRIVATE_KEY="5C1y..."
export ZERION_X402_PREFER_SOLANA=true
```
Pay-per-call applies to analytics commands only (`portfolio`, `positions`, `history`, `pnl`, `analyze`). Trading commands always use an API key.
### MPP pay-per-call
No API key needed. Pays \$0.01 USDC per request via the [MPP protocol](https://mpp.dev) on [Tempo](https://tempo.xyz). EVM only.
```bash theme={null}
export WALLET_PRIVATE_KEY="0x..." # or a dedicated key:
export TEMPO_PRIVATE_KEY="0x..."
zerion portfolio 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --mpp
```
Enable globally:
```bash theme={null}
export ZERION_MPP=true
```
## Skills
The CLI ships with six agent skills that install into AI coding agents. Each skill is self-contained — your agent loads the relevant one based on the user's intent.
| Skill | What it does |
| ------------------------- | ---------------------------------------------------------------------------------------------- |
| `zerion` | Umbrella entry — install, authentication, routing to capability skills, chains reference |
| `zerion-analyze` | Read-only wallet insights: portfolio, positions, history, PnL, watchlist (supports x402 / MPP) |
| `zerion-trading` | Swap, bridge, send tokens (on-chain actions; needs API key + agent token) |
| `zerion-sign` | Off-chain signing — sign-message (EIP-191 / raw), sign-typed-data (EIP-712) |
| `zerion-wallet` | Wallet management — create, import, list, fund, backup, delete, sync |
| `zerion-agent-management` | Agent tokens + policies (the autonomous-trading primitives) |
Install or reinstall skills:
```bash theme={null}
zerion setup skills # all detected agents (default: global)
zerion setup skills --agent claude-code # scope to one agent
zerion setup skills -g # force global install
```
Per-host plugin installs (alternative to `setup skills`):
```bash theme={null}
# Claude Code
/plugin marketplace add zeriontech/zerion-ai
/plugin install zerion-agent@zerion
# OpenAI Codex CLI
codex plugin marketplace add zeriontech/zerion-ai
# then run /plugins, choose the zerion marketplace, install zerion-agent
# Cursor
npx skills add zeriontech/zerion-ai --agent cursor
# OpenCode
npx skills add zeriontech/zerion-ai --agent opencode
# Gemini CLI
gemini extensions install https://github.com/zeriontech/zerion-ai
# Any agentskills.io host
npx skills add zeriontech/zerion-ai
```
## Manual setup, agent execution
The CLI splits cleanly into two surfaces, by design.
* **Wallet management and agent token setup are manual.** `wallet create`, `import`, `backup`, and `delete` prompt for a passphrase. `wallet sync` emits a QR code you scan with the Zerion app. `agent create-token` mints a scoped trading credential bound to a specific wallet, and `agent create-policy` attaches the rules it must obey — allowed chains, expiry, transfer/approval gates, contract allowlists. No key material moves and no spending credential widens without you in the loop.
* **Analysis, signing, trading, and discovery are for agents.** `analyze`, `portfolio`, `positions`, `history`, `pnl`, `sign-message`, `sign-typed-data`, `swap`, `bridge`, `send`, `search`, `chains`, and read-only listings emit JSON to stdout, structured errors to stderr, and skip confirmation dialogs. Once an agent token is configured, signing and trading fire immediately.
You stage by hand once — create or import a wallet, set a passphrase, mint an agent token, attach a policy — then hand the agent token to an automation that can only do what the policy allows. Treat agent tokens like API keys with spending power.
## Commands
Every command supports `--help` for full flag documentation. Run `zerion --help` for the top-level command list.
### Analyze
Read-only wallet insights. Supports `--x402` and `--mpp` for pay-per-call.
```bash theme={null}
# Full analysis — portfolio, positions, transactions, PnL in parallel
zerion analyze vitalik.eth
# Targeted reads
zerion portfolio 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
zerion positions vitalik.eth --defi # grouped by protocol, loans netted
zerion positions vitalik.eth --positions defi # flat list of DeFi positions
zerion history vitalik.eth --limit 10 --chain ethereum
zerion pnl vitalik.eth
```
#### Analyze Options
| Command | Description |
| --------------------------------- | -------------------------------------------------------------------------------------------------- |
| `zerion analyze ` | Full analysis — portfolio, positions, transactions, PnL in parallel |
| `zerion portfolio ` | Portfolio value and top positions |
| `zerion positions ` | Token + DeFi positions (`--positions all\|simple\|defi`, or `--defi` for grouped-by-protocol view) |
| `zerion history ` | Transaction history (`--limit`, `--chain`) |
| `zerion pnl ` | Profit & loss (realized, unrealized, fees) |
| `zerion search ` | Search tokens by name or symbol |
| `zerion chains` | List supported chains |
### Trade
Requires an API key plus an agent token for unattended use. Chain is the first positional argument.
```bash theme={null}
# Same-chain swap — zerion swap
zerion swap base 1 USDC ETH
zerion swap ethereum 0.1 ETH USDC
zerion swap solana 0.1 SOL USDC
zerion swap monad 1 USDC MON
# List tokens available for swap on a chain
zerion swap tokens base
zerion swap tokens solana
# Bridge — zerion bridge
# Default: list all provider offers (no transaction signed)
zerion bridge base USDC 5 arbitrum USDC
# Execute the highest-output offer
zerion bridge base USDC 5 arbitrum USDC --cheapest
# Execute the fastest offer
zerion bridge base USDC 5 arbitrum USDC --fast
# Bridge + swap on destination
zerion bridge base USDC 5 arbitrum ETH --cheapest
# Cross-format bridge (EVM ↔ Solana) — destination wallet required if source is EVM-only or Solana-only
zerion bridge ethereum USDC 50 solana USDC --to-wallet sol-bot --cheapest
zerion bridge ethereum USDC 50 solana USDC --to-address 8xLdox... --cheapest
# Send — chain auto-detected from recipient format
zerion send USDC 50 --to 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --chain base
zerion send SOL 0.1 --to 2Nsnn...
```
#### Trade Options
| Command | Description |
| ------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| `zerion swap ` | Same-chain swap |
| `zerion swap tokens [chain]` | List tokens available for swap |
| `zerion bridge ` | List all bridge providers (multi-offer mode; no execute) |
| `zerion bridge ... --cheapest` | Execute the highest-output offer |
| `zerion bridge ... --fast` | Execute the lowest-time offer (falls back to `--cheapest` if no time data) |
| `zerion bridge ... --to-wallet ` | Destination wallet for cross-format bridges (Solana ↔ EVM) |
| `zerion bridge ... --to-address ` | Raw destination address (must match destination-chain format) |
| `zerion send --to ` | Send tokens (chain auto-inferred from address format) |
| `zerion send SOL --to ` | Send native SOL on Solana |
`--fast` and `--cheapest` are mutually exclusive. When used, the strategy flag must come last on the command line so flag parsing doesn't consume the next positional as its value. Single-offer routes auto-execute even without a strategy flag.
### Sign
Off-chain signatures (EIP-191, EIP-712, Solana raw) — no broadcast. Requires an agent token.
```bash theme={null}
# EIP-191 (EVM) or raw (Solana)
zerion sign-message "Login to dApp" --chain ethereum
# Hex bytes
zerion sign-message 0xdeadbeef --encoding hex --chain ethereum
# EIP-712 typed data
zerion sign-typed-data --data "$(cat permit.json)"
zerion sign-typed-data --file permit.json
cat permit.json | zerion sign-typed-data
```
#### Sign Options
| Command | Description |
| ----------------------------------------------- | ------------------------------------------ |
| `zerion sign-message --chain ` | Sign EIP-191 (EVM) or raw (Solana) message |
| `zerion sign-message --encoding hex` | Treat message as hex bytes |
| `zerion sign-typed-data --data ''` | Sign EIP-712 typed data (EVM only) |
| `zerion sign-typed-data --file ` | Read EIP-712 typed data from file |
### Wallet
Encrypted local wallets. EVM + Solana supported. Passphrase required for destructive ops.
```bash theme={null}
zerion wallet create --name trading-bot
zerion wallet import --name old-wallet --evm-key
zerion wallet list
zerion wallet fund --wallet trading-bot
zerion wallet backup --wallet trading-bot
zerion wallet sync --wallet trading-bot
```
#### Wallet Options
| Command | Description |
| ----------------------------------------------- | -------------------------------------------- |
| `zerion wallet create --name ` | Create encrypted wallet (EVM + Solana) |
| `zerion wallet import --name --evm-key` | Import from EVM private key (interactive) |
| `zerion wallet import --name --sol-key` | Import from Solana private key (interactive) |
| `zerion wallet import --name --mnemonic` | Import from seed phrase (all chains) |
| `zerion wallet list` | List all wallets |
| `zerion wallet fund` | Show deposit addresses for funding |
| `zerion wallet backup --wallet ` | Export recovery phrase |
| `zerion wallet delete ` | Permanently delete a wallet |
| `zerion wallet sync --wallet ` | Sync wallet to Zerion app via QR code |
| `zerion wallet sync --all` | Sync all wallets |
### Agent
Scoped API tokens for unattended trading. Tokens auto-save to config and are required for `swap`, `bridge`, `send`.
```bash theme={null}
# Create a tight policy first
zerion agent create-policy --name safe-base \
--chains base \
--expires 24h \
--deny-transfers
# Mint a token bound to that policy
zerion agent create-token --name dca-bot \
--wallet trading-bot \
--policy safe-base
```
#### Agent Token Options
| Command | Description |
| ---------------------------------------------------------- | ----------------------------- |
| `zerion agent create-token --name --wallet ` | Create scoped token |
| `zerion agent list-tokens` | List active agent tokens |
| `zerion agent use-token --wallet ` | Switch active token by wallet |
| `zerion agent revoke-token --name ` | Revoke a token |
#### Agent Policy Options
| Command | Description |
| -------------------------------------------- | ------------------------------------ |
| `zerion agent create-policy --name ` | Create security policy (flags below) |
| `zerion agent list-policies` | List all policies |
| `zerion agent show-policy ` | Show policy details |
| `zerion agent delete-policy ` | Delete a policy |
#### Policy Flags
| Flag | Description |
| ------------------------- | --------------------------------------------- |
| `--chains ` | Restrict to specific chains (comma-separated) |
| `--expires ` | Token expiry (e.g. `24h`, `7d`) |
| `--deny-transfers` | Block raw ETH/native transfers |
| `--deny-approvals` | Block ERC-20 approval calls |
| `--allowlist ` | Only allow listed contract/wallet addresses |
### Watch
Track wallets by name without exposing addresses in commands.
```bash theme={null}
zerion watch 0xFe89Cc7Abb2C4183683Ab71653c4cCd1b9cC194e --name ens-dao
zerion analyze ens-dao
```
#### Watch Options
| Command | Description |
| --------------------------------------- | ----------------------- |
| `zerion watch --name