opensea
Query NFT data, trade on the Seaport marketplace, and swap ERC20 tokens across Ethereum, Base, Arbitrum, Optimism, Polygon, and more.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install openclaw-skills-opensea-skill
Repository
Skill path: skills/dfinzer/opensea-skill
Query NFT data, trade on the Seaport marketplace, and swap ERC20 tokens across Ethereum, Base, Arbitrum, Optimism, Polygon, and more.
Open repositoryBest for
Primary workflow: Analyze Data & AI.
Technical facets: Full Stack, Data / AI.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: openclaw.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install opensea into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/openclaw/skills before adding opensea to shared team environments
- Use opensea for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: opensea
description: Query NFT data, trade on the Seaport marketplace, and swap ERC20 tokens across Ethereum, Base, Arbitrum, Optimism, Polygon, and more.
---
# OpenSea API
Query NFT data, trade on the Seaport marketplace, and swap ERC20 tokens across Ethereum, Base, Arbitrum, Optimism, Polygon, and more.
## Quick start
1. Set `OPENSEA_API_KEY` in your environment
2. **Preferred:** Use the `opensea` CLI (`@opensea/cli`) for all queries and operations
3. Alternatively, use the shell scripts in `scripts/` or the MCP server
```bash
export OPENSEA_API_KEY="your-api-key"
# Install the CLI globally (or use npx)
npm install -g @opensea/cli
# Get collection info
opensea collections get boredapeyachtclub
# Get floor price and volume stats
opensea collections stats boredapeyachtclub
# Get NFT details
opensea nfts get ethereum 0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d 1234
# Get best listings for a collection
opensea listings best boredapeyachtclub --limit 5
# Search across OpenSea
opensea search "cool cats"
# Get trending tokens
opensea tokens trending --limit 5
# Get a swap quote
opensea swaps quote \
--from-chain base --from-address 0x0000000000000000000000000000000000000000 \
--to-chain base --to-address 0xTokenAddress \
--quantity 0.02 --address 0xYourWallet
```
## Task guide
> **Recommended:** Use the `opensea` CLI (`@opensea/cli`) as your primary tool. It covers all the operations below with a consistent interface, structured output, and built-in pagination. Install with `npm install -g @opensea/cli` or use `npx @opensea/cli`. The shell scripts in `scripts/` remain available as alternatives.
### Token swaps
OpenSea's API includes a cross-chain DEX aggregator for swapping ERC20 tokens with optimal routing across all supported chains.
| Task | CLI Command | Alternative |
|------|------------|-------------|
| Get swap quote with calldata | `opensea swaps quote --from-chain <chain> --from-address <addr> --to-chain <chain> --to-address <addr> --quantity <qty> --address <wallet>` | `get_token_swap_quote` (MCP) or `opensea-swap.sh` |
| Get trending tokens | `opensea tokens trending [--chains <chains>] [--limit <n>]` | `get_trending_tokens` (MCP) |
| Get top tokens by volume | `opensea tokens top [--chains <chains>] [--limit <n>]` | `get_top_tokens` (MCP) |
| Get token details | `opensea tokens get <chain> <address>` | `get_tokens` (MCP) |
| Search tokens | `opensea search <query> --types token` | `search_tokens` (MCP) |
| Check token balances | `get_token_balances` (MCP) | — |
### Reading NFT data
| Task | CLI Command | Alternative |
|------|------------|-------------|
| Get collection details | `opensea collections get <slug>` | `opensea-collection.sh <slug>` |
| Get collection stats | `opensea collections stats <slug>` | `opensea-collection-stats.sh <slug>` |
| List NFTs in collection | `opensea nfts list-by-collection <slug> [--limit <n>]` | `opensea-collection-nfts.sh <slug> [limit] [next]` |
| Get single NFT | `opensea nfts get <chain> <contract> <token_id>` | `opensea-nft.sh <chain> <contract> <token_id>` |
| List NFTs by wallet | `opensea nfts list-by-account <chain> <address> [--limit <n>]` | `opensea-account-nfts.sh <chain> <address> [limit]` |
| List NFTs by contract | `opensea nfts list-by-contract <chain> <contract> [--limit <n>]` | — |
| Get collection traits | `opensea collections traits <slug>` | — |
| Get contract details | `opensea nfts contract <chain> <address>` | — |
| Refresh NFT metadata | `opensea nfts refresh <chain> <contract> <token_id>` | — |
### Marketplace queries
| Task | CLI Command | Alternative |
|------|------------|-------------|
| Get best listings for collection | `opensea listings best <slug> [--limit <n>]` | `opensea-best-listing.sh <slug> <token_id>` |
| Get best listing for specific NFT | `opensea listings best-for-nft <slug> <token_id>` | `opensea-best-listing.sh <slug> <token_id>` |
| Get best offer for NFT | `opensea offers best-for-nft <slug> <token_id>` | `opensea-best-offer.sh <slug> <token_id>` |
| List all collection listings | `opensea listings all <slug> [--limit <n>]` | `opensea-listings-collection.sh <slug> [limit]` |
| List all collection offers | `opensea offers all <slug> [--limit <n>]` | `opensea-offers-collection.sh <slug> [limit]` |
| Get collection offers | `opensea offers collection <slug> [--limit <n>]` | `opensea-offers-collection.sh <slug> [limit]` |
| Get trait offers | `opensea offers traits <slug> --type <type> --value <value>` | — |
| Get order by hash | — | `opensea-order.sh <chain> <order_hash>` |
### Marketplace actions (POST)
| Task | Script |
|------|--------|
| Get fulfillment data (buy NFT) | `opensea-fulfill-listing.sh <chain> <order_hash> <buyer>` |
| Get fulfillment data (accept offer) | `opensea-fulfill-offer.sh <chain> <order_hash> <seller> <contract> <token_id>` |
| Generic POST request | `opensea-post.sh <path> <json_body>` |
### Search
| Task | CLI Command |
|------|------------|
| Search collections | `opensea search <query> --types collection` |
| Search NFTs | `opensea search <query> --types nft` |
| Search tokens | `opensea search <query> --types token` |
| Search accounts | `opensea search <query> --types account` |
| Search multiple types | `opensea search <query> --types collection,nft,token` |
| Search on specific chain | `opensea search <query> --chains base,ethereum` |
### Events and monitoring
| Task | CLI Command | Alternative |
|------|------------|-------------|
| List recent events | `opensea events list [--event-type <type>] [--limit <n>]` | — |
| Get collection events | `opensea events by-collection <slug> [--event-type <type>]` | `opensea-events-collection.sh <slug> [event_type] [limit]` |
| Get events for specific NFT | `opensea events by-nft <chain> <contract> <token_id>` | — |
| Get events for account | `opensea events by-account <address>` | — |
| Stream real-time events | — | `opensea-stream-collection.sh <slug>` (requires websocat) |
Event types: `sale`, `transfer`, `mint`, `listing`, `offer`, `trait_offer`, `collection_offer`
### Accounts
| Task | CLI Command |
|------|------------|
| Get account details | `opensea accounts get <address>` |
### Generic requests
| Task | Script |
|------|--------|
| Any GET endpoint | `opensea-get.sh <path> [query]` |
| Any POST endpoint | `opensea-post.sh <path> <json_body>` |
## Buy/Sell workflows
### Buying an NFT
1. Find the NFT and check its listing:
```bash
./scripts/opensea-best-listing.sh cool-cats-nft 1234
```
2. Get the order hash from the response, then get fulfillment data:
```bash
./scripts/opensea-fulfill-listing.sh ethereum 0x_order_hash 0x_your_wallet
```
3. The response contains transaction data to execute on-chain
### Selling an NFT (accepting an offer)
1. Check offers on your NFT:
```bash
./scripts/opensea-best-offer.sh cool-cats-nft 1234
```
2. Get fulfillment data for the offer:
```bash
./scripts/opensea-fulfill-offer.sh ethereum 0x_offer_hash 0x_your_wallet 0x_nft_contract 1234
```
3. Execute the returned transaction data
### Creating listings/offers
Creating new listings and offers requires wallet signatures. Use `opensea-post.sh` with the Seaport order structure - see `references/marketplace-api.md` for full details.
## OpenSea CLI (`@opensea/cli`)
The [OpenSea CLI](https://github.com/ProjectOpenSea/opensea-cli) is the recommended way for AI agents to interact with OpenSea. It provides a consistent command-line interface and a programmatic TypeScript/JavaScript SDK.
### Installation
```bash
# Install globally
npm install -g @opensea/cli
# Or use without installing
npx @opensea/cli collections get mfers
```
### Authentication
```bash
# Set via environment variable (recommended)
export OPENSEA_API_KEY="your-api-key"
opensea collections get mfers
# Or pass inline
opensea --api-key your-api-key collections get mfers
```
### CLI Commands
| Command | Description |
|---|---|
| `collections` | Get, list, stats, and traits for NFT collections |
| `nfts` | Get, list, refresh metadata, and contract details for NFTs |
| `listings` | Get all, best, or best-for-nft listings |
| `offers` | Get all, collection, best-for-nft, and trait offers |
| `events` | List marketplace events (sales, transfers, mints, etc.) |
| `search` | Search collections, NFTs, tokens, and accounts |
| `tokens` | Get trending tokens, top tokens, and token details |
| `swaps` | Get swap quotes for token trading |
| `accounts` | Get account details |
Global options: `--api-key`, `--chain` (default: ethereum), `--format` (json/table/toon), `--base-url`, `--timeout`, `--verbose`
### Output Formats
- **JSON** (default): Structured output for agents and scripts
- **Table**: Human-readable tabular output (`--format table`)
- **TOON**: Token-Oriented Object Notation, uses ~40% fewer tokens than JSON — ideal for LLM/AI agent context windows (`--format toon`)
```bash
# JSON output (default)
opensea collections stats mfers
# Human-readable table
opensea --format table collections stats mfers
# Compact TOON format (best for AI agents)
opensea --format toon tokens trending --limit 5
```
### Pagination
All list commands support cursor-based pagination with `--limit` and `--next`:
```bash
# First page
opensea collections list --limit 5
# Pass the "next" cursor from the response to get the next page
opensea collections list --limit 5 --next "LXBrPTEwMDA..."
```
### Programmatic SDK
The CLI also exports a TypeScript/JavaScript SDK for use in scripts and applications:
```typescript
import { OpenSeaCLI, OpenSeaAPIError } from "@opensea/cli"
const client = new OpenSeaCLI({ apiKey: process.env.OPENSEA_API_KEY })
const collection = await client.collections.get("mfers")
const { nfts } = await client.nfts.listByCollection("mfers", { limit: 5 })
const { listings } = await client.listings.best("mfers", { limit: 10 })
const { asset_events } = await client.events.byCollection("mfers", { eventType: "sale" })
const { tokens } = await client.tokens.trending({ chains: ["base"], limit: 5 })
const results = await client.search.query("mfers", { limit: 5 })
// Swap quote
const { quote, transactions } = await client.swaps.quote({
fromChain: "base",
fromAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
toChain: "base",
toAddress: "0x3ec2156d4c0a9cbdab4a016633b7bcf6a8d68ea2",
quantity: "1000000",
address: "0xYourWalletAddress",
})
// Error handling
try {
await client.collections.get("nonexistent")
} catch (error) {
if (error instanceof OpenSeaAPIError) {
console.error(error.statusCode) // e.g. 404
console.error(error.responseBody) // raw API response
console.error(error.path) // request path
}
}
```
### TOON Format for AI Agents
TOON (Token-Oriented Object Notation) is a compact serialization format that uses ~40% fewer tokens than JSON, making it ideal for piping CLI output into LLM context windows:
```bash
opensea --format toon tokens trending --limit 3
```
Example output:
```
tokens[3]{name,symbol,chain,market_cap,price_usd}:
Ethereum,ETH,ethereum,250000000000,2100.50
Bitcoin,BTC,bitcoin,900000000000,48000.00
Solana,SOL,solana,30000000000,95.25
next: abc123
```
TOON is also available programmatically:
```typescript
import { formatToon } from "@opensea/cli"
const data = await client.tokens.trending({ limit: 5 })
console.log(formatToon(data))
```
### CLI Exit Codes
- `0` - Success
- `1` - API error
- `2` - Authentication error
---
## Shell Scripts Reference
The `scripts/` directory contains shell scripts that wrap the OpenSea REST API directly using `curl`. These are an alternative to the CLI above.
### NFT & Collection Scripts
| Script | Purpose |
|--------|---------|
| `opensea-get.sh` | Generic GET (path + optional query) |
| `opensea-post.sh` | Generic POST (path + JSON body) |
| `opensea-collection.sh` | Fetch collection by slug |
| `opensea-collection-stats.sh` | Fetch collection statistics |
| `opensea-collection-nfts.sh` | List NFTs in collection |
| `opensea-nft.sh` | Fetch single NFT by chain/contract/token |
| `opensea-account-nfts.sh` | List NFTs owned by wallet |
### Marketplace Scripts
| Script | Purpose |
|--------|---------|
| `opensea-listings-collection.sh` | All listings for collection |
| `opensea-listings-nft.sh` | Listings for specific NFT |
| `opensea-offers-collection.sh` | All offers for collection |
| `opensea-offers-nft.sh` | Offers for specific NFT |
| `opensea-best-listing.sh` | Lowest listing for NFT |
| `opensea-best-offer.sh` | Highest offer for NFT |
| `opensea-order.sh` | Get order by hash |
| `opensea-fulfill-listing.sh` | Get buy transaction data |
| `opensea-fulfill-offer.sh` | Get sell transaction data |
### Token Swap Scripts
| Script | Purpose |
|--------|---------|
| `opensea-swap.sh` | **Swap tokens via OpenSea MCP** |
### Monitoring Scripts
| Script | Purpose |
|--------|---------|
| `opensea-events-collection.sh` | Collection event history |
| `opensea-stream-collection.sh` | Real-time WebSocket events |
## Supported chains
`ethereum`, `matic`, `arbitrum`, `optimism`, `base`, `avalanche`, `klaytn`, `zora`, `blast`, `sepolia`
## References
- [OpenSea CLI GitHub](https://github.com/ProjectOpenSea/opensea-cli) - Full CLI and SDK documentation
- [CLI Reference](https://github.com/ProjectOpenSea/opensea-cli/blob/main/docs/cli-reference.md) - Complete command reference
- [SDK Reference](https://github.com/ProjectOpenSea/opensea-cli/blob/main/docs/sdk.md) - Programmatic SDK API
- [CLI Examples](https://github.com/ProjectOpenSea/opensea-cli/blob/main/docs/examples.md) - Real-world usage examples
- `references/rest-api.md` - REST endpoint families and pagination
- `references/marketplace-api.md` - Buy/sell workflows and Seaport details
- `references/stream-api.md` - WebSocket event streaming
- `references/seaport.md` - Seaport protocol and NFT purchase execution
- `references/token-swaps.md` - **Token swap workflows via MCP**
## OpenSea MCP Server
An official OpenSea MCP server provides direct LLM integration for token swaps and NFT operations. When enabled, Claude can execute swaps, query token data, and interact with NFT marketplaces directly.
**Setup:**
1. Go to the [OpenSea Developer Portal](https://opensea.io/settings/developer) and verify your email
2. Generate a new API key for REST API access
3. Generate a separate MCP token for the MCP server
Add to your MCP config:
```json
{
"mcpServers": {
"opensea": {
"url": "https://mcp.opensea.io/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_TOKEN"
}
}
}
}
```
Or use the inline token format: `https://mcp.opensea.io/YOUR_MCP_TOKEN/mcp`
### Token Swap Tools
| MCP Tool | Purpose |
|----------|---------|
| `get_token_swap_quote` | **Get swap calldata for token trades** |
| `get_token_balances` | Check wallet token holdings |
| `search_tokens` | Find tokens by name/symbol |
| `get_trending_tokens` | Hot tokens by momentum |
| `get_top_tokens` | Top tokens by 24h volume |
| `get_tokens` | Get detailed token info |
### NFT Tools
| MCP Tool | Purpose |
|----------|---------|
| `search_collections` | Search NFT collections |
| `search_items` | Search individual NFTs |
| `get_collections` | Get detailed collection info |
| `get_items` | Get detailed NFT info |
| `get_nft_balances` | List NFTs owned by wallet |
| `get_trending_collections` | Trending NFT collections |
| `get_top_collections` | Top collections by volume |
| `get_activity` | Trading activity for collections/items |
| `get_upcoming_drops` | Upcoming NFT mints |
### Profile & Utility Tools
| MCP Tool | Purpose |
|----------|---------|
| `get_profile` | Wallet profile with holdings/activity |
| `account_lookup` | Resolve ENS/address/username |
| `get_chains` | List supported chains |
| `search` | AI-powered natural language search |
| `fetch` | Get full details by entity ID |
---
## Token Swaps via MCP
OpenSea MCP supports ERC20 token swaps across supported DEXes - not just NFTs!
### Get Swap Quote
```bash
mcporter call opensea.get_token_swap_quote --args '{
"fromContractAddress": "0x0000000000000000000000000000000000000000",
"fromChain": "base",
"toContractAddress": "0xb695559b26bb2c9703ef1935c37aeae9526bab07",
"toChain": "base",
"fromQuantity": "0.02",
"address": "0xYourWalletAddress"
}'
```
**Parameters:**
- `fromContractAddress`: Token to swap from (use `0x0000...0000` for native ETH)
- `toContractAddress`: Token to swap to
- `fromChain` / `toChain`: Chain identifiers
- `fromQuantity`: Amount in human-readable units (e.g., "0.02" for 0.02 ETH)
- `address`: Your wallet address
**Response includes:**
- `swapQuote`: Price info, fees, slippage impact
- `swap.actions[0].transactionSubmissionData`: Ready-to-use calldata
### Execute the Swap
```javascript
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
// Extract from swap quote response
const txData = response.swap.actions[0].transactionSubmissionData;
const wallet = createWalletClient({
account: privateKeyToAccount(PRIVATE_KEY),
chain: base,
transport: http()
});
const hash = await wallet.sendTransaction({
to: txData.to,
data: txData.data,
value: BigInt(txData.value)
});
```
### Check Token Balances
```bash
mcporter call opensea.get_token_balances --args '{
"address": "0xYourWallet",
"chains": ["base", "ethereum"]
}'
```
## Generating a wallet
To execute swaps or buy NFTs, you need an Ethereum wallet (private key + address).
### Using Node.js
```javascript
import crypto from 'crypto';
import { privateKeyToAccount } from 'viem/accounts';
const privateKey = '0x' + crypto.randomBytes(32).toString('hex');
const account = privateKeyToAccount(privateKey);
console.log('Private Key:', privateKey);
console.log('Address:', account.address);
```
### Using OpenSSL
```bash
# Generate private key
PRIVATE_KEY="0x$(openssl rand -hex 32)"
echo "Private Key: $PRIVATE_KEY"
# Derive address (requires node + viem)
node --input-type=module -e "
import { privateKeyToAccount } from 'viem/accounts';
console.log('Address:', privateKeyToAccount('$PRIVATE_KEY').address);
"
```
### Using cast (Foundry)
```bash
cast wallet new
```
**Important:** Store private keys securely. Never commit them to git or share publicly.
## Requirements
- `OPENSEA_API_KEY` environment variable (for CLI, SDK, and REST API scripts)
- `OPENSEA_MCP_TOKEN` environment variable (for MCP server, separate from API key)
- Node.js >= 18.0.0 (for `@opensea/cli`)
- `curl` for REST shell scripts
- `websocat` (optional) for Stream API
- `jq` (recommended) for parsing JSON responses from shell scripts
Get both credentials at [opensea.io/settings/developer](https://opensea.io/settings/developer).
---
## Referenced Files
> The following files are referenced in this skill and included for context.
### scripts/opensea-best-listing.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 2 ]; then
echo "Usage: opensea-best-listing.sh <collection_slug> <token_id>" >&2
echo "Example: opensea-best-listing.sh boredapeyachtclub 1234" >&2
exit 1
fi
slug="$1"
token_id="$2"
"$(dirname "$0")/opensea-get.sh" "/api/v2/listings/collection/${slug}/nfts/${token_id}/best"
```
### scripts/opensea-fulfill-listing.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 3 ]; then
echo "Usage: opensea-fulfill-listing.sh <chain> <order_hash> <fulfiller_address>" >&2
echo "Returns transaction data to execute on-chain to buy the NFT" >&2
echo "Example: opensea-fulfill-listing.sh ethereum 0x1234... 0xYourWallet" >&2
exit 1
fi
chain="$1"
order_hash="$2"
fulfiller="$3"
protocol="0x0000000000000068f116a894984e2db1123eb395"
body=$(cat <<EOF
{
"listing": {
"hash": "$order_hash",
"chain": "$chain",
"protocol_address": "$protocol"
},
"fulfiller": {
"address": "$fulfiller"
}
}
EOF
)
"$(dirname "$0")/opensea-post.sh" "/api/v2/listings/fulfillment_data" "$body"
```
### scripts/opensea-best-offer.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 2 ]; then
echo "Usage: opensea-best-offer.sh <collection_slug> <token_id>" >&2
echo "Example: opensea-best-offer.sh boredapeyachtclub 1234" >&2
exit 1
fi
slug="$1"
token_id="$2"
"$(dirname "$0")/opensea-get.sh" "/api/v2/offers/collection/${slug}/nfts/${token_id}/best"
```
### scripts/opensea-fulfill-offer.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 5 ]; then
echo "Usage: opensea-fulfill-offer.sh <chain> <order_hash> <fulfiller_address> <contract_address> <token_id>" >&2
echo "Returns transaction data to execute on-chain to accept an offer (sell NFT)" >&2
echo "Example: opensea-fulfill-offer.sh ethereum 0x1234... 0xYourWallet 0xContract 5678" >&2
exit 1
fi
chain="$1"
order_hash="$2"
fulfiller="$3"
contract="$4"
token_id="$5"
protocol="0x0000000000000068f116a894984e2db1123eb395"
body=$(cat <<EOF
{
"offer": {
"hash": "$order_hash",
"chain": "$chain",
"protocol_address": "$protocol"
},
"fulfiller": {
"address": "$fulfiller"
},
"consideration": {
"asset_contract_address": "$contract",
"token_id": "$token_id"
}
}
EOF
)
"$(dirname "$0")/opensea-post.sh" "/api/v2/offers/fulfillment_data" "$body"
```
### references/marketplace-api.md
```markdown
# OpenSea Marketplace API
This reference covers the marketplace endpoints for buying and selling NFTs on OpenSea.
## Overview
OpenSea uses the **Seaport protocol** for all marketplace orders. The API provides endpoints to:
- Query existing listings and offers
- Build new listings and offers (returns unsigned Seaport orders)
- Fulfill orders (accept listings or offers)
- Cancel orders
**Important**: Creating and fulfilling orders requires wallet signatures. The API returns order data that must be signed client-side before submission.
## Base URL and Authentication
```
Base URL: https://api.opensea.io/api/v2
Auth: x-api-key: $OPENSEA_API_KEY
```
## Supported Chains
| Chain | Identifier |
|-------|------------|
| Ethereum | `ethereum` |
| Polygon | `matic` |
| Arbitrum | `arbitrum` |
| Optimism | `optimism` |
| Base | `base` |
| Avalanche | `avalanche` |
| Klaytn | `klaytn` |
| Zora | `zora` |
| Blast | `blast` |
| Sepolia (testnet) | `sepolia` |
---
## Read Operations (GET)
### Get Best Listing for NFT
Returns the lowest-priced active listing for an NFT.
```bash
GET /api/v2/listings/collection/{collection_slug}/nfts/{identifier}/best
```
**Parameters:**
- `collection_slug`: Collection slug (e.g., `boredapeyachtclub`)
- `identifier`: NFT identifier (token ID)
**Example:**
```bash
scripts/opensea-get.sh "/api/v2/listings/collection/boredapeyachtclub/nfts/1234/best"
```
### Get Best Offer for NFT
Returns the highest active offer for an NFT.
```bash
GET /api/v2/offers/collection/{collection_slug}/nfts/{identifier}/best
```
**Example:**
```bash
scripts/opensea-get.sh "/api/v2/offers/collection/boredapeyachtclub/nfts/1234/best"
```
### Get All Listings for Collection
Returns all active listings for a collection.
```bash
GET /api/v2/listings/collection/{collection_slug}/all
```
**Query parameters:**
- `limit`: Page size (default 50, max 100)
- `next`: Cursor for pagination
**Example:**
```bash
scripts/opensea-listings-collection.sh boredapeyachtclub 50
```
### Get All Offers for Collection
Returns all active offers for a collection.
```bash
GET /api/v2/offers/collection/{collection_slug}/all
```
**Example:**
```bash
scripts/opensea-offers-collection.sh boredapeyachtclub 50
```
### Get Listings for Specific NFT
```bash
GET /api/v2/orders/{chain}/seaport/listings
```
**Query parameters:**
- `asset_contract_address`: Contract address
- `token_ids`: Comma-separated token IDs
- `limit`, `next`: Pagination
**Example:**
```bash
scripts/opensea-get.sh "/api/v2/orders/ethereum/seaport/listings" "asset_contract_address=0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&token_ids=1234"
```
### Get Offers for Specific NFT
```bash
GET /api/v2/orders/{chain}/seaport/offers
```
**Query parameters:**
- `asset_contract_address`: Contract address
- `token_ids`: Comma-separated token IDs
**Example:**
```bash
scripts/opensea-get.sh "/api/v2/orders/ethereum/seaport/offers" "asset_contract_address=0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&token_ids=1234"
```
### Get Order by Hash
Retrieve details of a specific order.
```bash
GET /api/v2/orders/chain/{chain}/protocol/{protocol_address}/hash/{order_hash}
```
**Example:**
```bash
scripts/opensea-get.sh "/api/v2/orders/chain/ethereum/protocol/0x0000000000000068f116a894984e2db1123eb395/hash/0x..."
```
---
## Write Operations (POST)
### Build a Listing
Creates an unsigned Seaport listing order. Returns order parameters to sign.
```bash
POST /api/v2/orders/{chain}/seaport/listings
```
**Request body:**
```json
{
"parameters": {
"offerer": "0xYourWalletAddress",
"offer": [{
"itemType": 2,
"token": "0xContractAddress",
"identifierOrCriteria": "1234",
"startAmount": "1",
"endAmount": "1"
}],
"consideration": [{
"itemType": 0,
"token": "0x0000000000000000000000000000000000000000",
"identifierOrCriteria": "0",
"startAmount": "1000000000000000000",
"endAmount": "1000000000000000000",
"recipient": "0xYourWalletAddress"
}],
"startTime": "1704067200",
"endTime": "1735689600",
"orderType": 0,
"zone": "0x0000000000000000000000000000000000000000",
"zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"salt": "random_salt_value",
"conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
"totalOriginalConsiderationItems": 1
},
"signature": "0xSignedOrderSignature"
}
```
**Item Types:**
- `0`: Native currency (ETH, MATIC, etc.)
- `1`: ERC20 token
- `2`: ERC721 NFT
- `3`: ERC1155 NFT
**Example (curl):**
```bash
curl -X POST "https://api.opensea.io/api/v2/orders/ethereum/seaport/listings" \
-H "x-api-key: $OPENSEA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"parameters": {...}, "signature": "0x..."}'
```
### Build an Offer
Creates an unsigned Seaport offer order.
```bash
POST /api/v2/orders/{chain}/seaport/offers
```
**Request body structure** (similar to listings, but offer contains payment and consideration contains NFT):
```json
{
"parameters": {
"offerer": "0xBuyerWalletAddress",
"offer": [{
"itemType": 1,
"token": "0xWETHAddress",
"identifierOrCriteria": "0",
"startAmount": "1000000000000000000",
"endAmount": "1000000000000000000"
}],
"consideration": [{
"itemType": 2,
"token": "0xNFTContractAddress",
"identifierOrCriteria": "1234",
"startAmount": "1",
"endAmount": "1",
"recipient": "0xBuyerWalletAddress"
}]
},
"signature": "0x..."
}
```
### Fulfill a Listing (Buy NFT)
Accept an existing listing to purchase an NFT.
```bash
POST /api/v2/listings/fulfillment_data
```
**Request body:**
```json
{
"listing": {
"hash": "0xOrderHash",
"chain": "ethereum",
"protocol_address": "0x0000000000000068f116a894984e2db1123eb395"
},
"fulfiller": {
"address": "0xBuyerWalletAddress"
}
}
```
**Response:** Returns transaction data for the buyer to submit on-chain.
### Fulfill an Offer (Sell NFT)
Accept an existing offer to sell your NFT.
```bash
POST /api/v2/offers/fulfillment_data
```
**Request body:**
```json
{
"offer": {
"hash": "0xOfferOrderHash",
"chain": "ethereum",
"protocol_address": "0x0000000000000068f116a894984e2db1123eb395"
},
"fulfiller": {
"address": "0xSellerWalletAddress"
},
"consideration": {
"asset_contract_address": "0xNFTContract",
"token_id": "1234"
}
}
```
### Cancel an Order
Cancel an active listing or offer.
```bash
POST /api/v2/orders/chain/{chain}/protocol/{protocol_address}/hash/{order_hash}/cancel
```
**Note:** Cancellation requires an on-chain transaction. The API returns the transaction data to execute.
---
## Workflow: Buying an NFT
1. **Find the NFT** - Use `opensea-nft.sh` to get NFT details
2. **Check listings** - Use `opensea-get.sh` to get best listing
3. **Get fulfillment data** - POST to `/api/v2/listings/fulfillment_data`
4. **Execute transaction** - Sign and submit the returned transaction data
```bash
# Step 1: Get NFT info
./scripts/opensea-nft.sh ethereum 0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d 1234
# Step 2: Get best listing
./scripts/opensea-get.sh "/api/v2/listings/collection/boredapeyachtclub/nfts/1234/best"
# Step 3: Request fulfillment (requires POST - see marketplace scripts)
./scripts/opensea-fulfill-listing.sh ethereum 0x_order_hash 0x_your_wallet
```
## Workflow: Selling an NFT (Creating a Listing)
1. **Build the listing** - POST to `/api/v2/orders/{chain}/seaport/listings`
2. **Sign the order** - Use wallet to sign the Seaport order
3. **Submit signed order** - POST again with signature
4. **Monitor** - Check listing via `/api/v2/listings/collection/{slug}/all`
## Workflow: Making an Offer
1. **Ensure WETH approval** - Buyer needs WETH allowance for Seaport
2. **Build the offer** - POST to `/api/v2/orders/{chain}/seaport/offers`
3. **Sign the order** - Wallet signature required
4. **Submit** - POST with signature
## Workflow: Accepting an Offer
1. **View offers** - Use `opensea-offers-collection.sh`
2. **Get fulfillment data** - POST to `/api/v2/offers/fulfillment_data`
3. **Execute** - Submit the returned transaction
---
## Error Codes
| Code | Meaning |
|------|---------|
| 400 | Bad request - invalid parameters |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not found - order/NFT doesn't exist |
| 429 | Rate limited - too many requests |
| 500 | Server error |
## Rate Limits
- Standard: 60 requests/minute
- With API key: Higher limits (check your dashboard)
---
## Seaport Contract Addresses
| Chain | Seaport 1.6 Address |
|-------|---------------------|
| All chains | `0x0000000000000068F116a894984e2DB1123eB395` |
---
## Tips
1. **Always use WETH for offers** - Native ETH cannot be used for offers due to ERC20 approval requirements
2. **Check approval status** - Before creating listings, ensure Seaport has approval for your NFTs
3. **Test on Sepolia first** - Use testnet before mainnet transactions
4. **Handle expiration** - Orders have startTime/endTime - check these before fulfilling
5. **Monitor events** - Use Stream API for real-time order updates
```
### references/rest-api.md
```markdown
# OpenSea REST API Reference
## Base URL and Authentication
```
Base URL: https://api.opensea.io
Auth header: x-api-key: $OPENSEA_API_KEY
```
## Pagination
List endpoints support cursor-based pagination:
- `limit`: Page size (default varies, max 100)
- `next`: Cursor token from previous response
## Supported Chains
| Chain | Identifier |
|-------|------------|
| Ethereum | `ethereum` |
| Polygon | `matic` |
| Arbitrum | `arbitrum` |
| Optimism | `optimism` |
| Base | `base` |
| Avalanche | `avalanche` |
| Klaytn | `klaytn` |
| Zora | `zora` |
| Blast | `blast` |
| Sepolia (testnet) | `sepolia` |
## Endpoint Reference
### Collections
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v2/collections/{slug}` | GET | Single collection details |
| `/api/v2/collections/{slug}/stats` | GET | Collection statistics (floor, volume) |
| `/api/v2/collections` | GET | List multiple collections |
### NFTs
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v2/chain/{chain}/contract/{contract}/nfts/{token_id}` | GET | Single NFT details |
| `/api/v2/collection/{slug}/nfts` | GET | NFTs by collection |
| `/api/v2/chain/{chain}/account/{address}/nfts` | GET | NFTs by wallet |
| `/api/v2/chain/{chain}/contract/{contract}/nfts` | GET | NFTs by contract |
| `/api/v2/nft/{contract}/{token_id}/refresh` | POST | Refresh NFT metadata |
### Listings
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v2/listings/collection/{slug}/all` | GET | All listings for collection |
| `/api/v2/listings/collection/{slug}/nfts/{token_id}/best` | GET | Best listing for NFT |
| `/api/v2/orders/{chain}/seaport/listings` | GET | Listings by contract/token |
| `/api/v2/orders/{chain}/seaport/listings` | POST | Create new listing |
| `/api/v2/listings/fulfillment_data` | POST | Get buy transaction data |
### Offers
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v2/offers/collection/{slug}/all` | GET | All offers for collection |
| `/api/v2/offers/collection/{slug}/nfts/{token_id}/best` | GET | Best offer for NFT |
| `/api/v2/orders/{chain}/seaport/offers` | GET | Offers by contract/token |
| `/api/v2/orders/{chain}/seaport/offers` | POST | Create new offer |
| `/api/v2/offers/fulfillment_data` | POST | Get sell transaction data |
### Orders
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v2/orders/chain/{chain}/protocol/{protocol}/{hash}` | GET | Get order by hash |
| `/api/v2/orders/chain/{chain}/protocol/{protocol}/{hash}/cancel` | POST | Cancel order |
### Events
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v2/events/collection/{slug}` | GET | Events by collection |
| `/api/v2/events/chain/{chain}/contract/{contract}/nfts/{token_id}` | GET | Events by NFT |
| `/api/v2/events/chain/{chain}/account/{address}` | GET | Events by account |
### Accounts
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v2/accounts/{address}` | GET | Account profile |
## Event Types
For the events endpoint, filter with `event_type`:
- `sale` - NFT sold
- `transfer` - NFT transferred
- `listing` - New listing created
- `offer` - New offer made
- `cancel` - Order cancelled
- `redemption` - NFT redeemed
## Rate Limits
- Without API key: 40 requests/minute
- With API key: Higher limits (varies by tier)
## Error Codes
| Code | Meaning |
|------|---------|
| 400 | Bad request - check parameters |
| 401 | Unauthorized - missing/invalid API key |
| 404 | Resource not found |
| 429 | Rate limited |
| 500 | Server error |
## Tips
1. Use collection slugs (not addresses) for collection endpoints
2. Use chain identifiers for NFT/account endpoints
3. All timestamps are Unix epoch seconds
4. Prices are in wei (divide by 10^18 for ETH)
5. Use `jq` to parse JSON responses: `./script.sh | jq '.nft.name'`
```
### references/stream-api.md
```markdown
# OpenSea Stream API (WebSocket)
## Base endpoint
wss://stream.openseabeta.com/socket/websocket?token=YOUR_API_KEY
## Join a collection channel
Send a Phoenix join message:
{"topic":"collection:your-collection-slug","event":"phx_join","payload":{},"ref":1}
Use "collection:*" to subscribe globally.
## Heartbeat
Send every ~30 seconds:
{"topic":"phoenix","event":"heartbeat","payload":{},"ref":0}
## Event types
- item_metadata_updated
- item_listed
- item_sold
- item_transferred
- item_received_bid
- item_cancelled
## Notes
- Stream is WebSocket-based, not HTTP. curl is not suitable.
- Use scripts/opensea-stream-collection.sh (websocat preferred).
```
### references/seaport.md
```markdown
# Seaport (OpenSea marketplace protocol)
## What it is
Seaport is the marketplace protocol used for OpenSea orders. All listings and offers on OpenSea are Seaport orders under the hood.
## Order structure
- **Offer items**: What the offerer provides (e.g., an NFT for listings, WETH for offers)
- **Consideration items**: What the offerer expects to receive (e.g., ETH payment + fees)
## Seaport Contract Addresses
| Chain | Seaport 1.6 Address |
|-------|---------------------|
| All EVM chains | `0x0000000000000068F116a894984e2DB1123eB395` |
Legacy Seaport 1.5: `0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC`
---
## Buying NFTs (Fulfilling Listings)
**No SDK required!** The OpenSea API returns ready-to-use calldata.
### Workflow
1. **Find a listing** - Get order hash from listings endpoint
2. **Get fulfillment data** - POST to fulfillment endpoint
3. **Submit transaction** - Send calldata directly to blockchain
### Step 1: Get Listings
```bash
# Via script
./scripts/opensea-listings-collection.sh basenames
# Via MCP
mcporter call opensea.get_listings collection="basenames" limit=10
```
Note the `order_hash` and `protocol_address` from the response.
### Step 2: Get Fulfillment Calldata
```bash
# Via script
./scripts/opensea-fulfill-listing.sh base 0xORDER_HASH 0xYOUR_WALLET
# Via curl
curl -X POST "https://api.opensea.io/api/v2/listings/fulfillment_data" \
-H "Content-Type: application/json" \
-H "x-api-key: $OPENSEA_API_KEY" \
-d '{
"listing": {
"hash": "0xORDER_HASH",
"chain": "base",
"protocol_address": "0x0000000000000068F116a894984e2DB1123eB395"
},
"fulfiller": {
"address": "0xYOUR_WALLET"
}
}'
```
**Response contains:**
- `fulfillment_data.transaction.to` - Seaport contract
- `fulfillment_data.transaction.value` - ETH to send (wei)
- `fulfillment_data.transaction.input_data` - Encoded calldata
### Step 3: Submit Transaction
```javascript
import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
const account = privateKeyToAccount(PRIVATE_KEY);
const wallet = createWalletClient({ account, chain: base, transport: http() });
const pub = createPublicClient({ chain: base, transport: http() });
// From fulfillment response
const txData = response.fulfillment_data.transaction;
const hash = await wallet.sendTransaction({
to: txData.to,
data: txData.input_data.parameters ? encodeSeaportCall(txData.input_data) : txData.data,
value: BigInt(txData.value)
});
const receipt = await pub.waitForTransactionReceipt({ hash });
console.log(receipt.status === 'success' ? '✅ NFT purchased!' : '❌ Failed');
```
### Complete Working Example
```javascript
// buy-nft.mjs - Buy an NFT via OpenSea fulfillment API
import { createPublicClient, createWalletClient, http, encodeFunctionData } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
const SEAPORT_ABI = [{
name: 'fulfillBasicOrder_efficient_6GL6yc',
type: 'function',
stateMutability: 'payable',
inputs: [{
name: 'parameters',
type: 'tuple',
components: [
{ name: 'considerationToken', type: 'address' },
{ name: 'considerationIdentifier', type: 'uint256' },
{ name: 'considerationAmount', type: 'uint256' },
{ name: 'offerer', type: 'address' },
{ name: 'zone', type: 'address' },
{ name: 'offerToken', type: 'address' },
{ name: 'offerIdentifier', type: 'uint256' },
{ name: 'offerAmount', type: 'uint256' },
{ name: 'basicOrderType', type: 'uint8' },
{ name: 'startTime', type: 'uint256' },
{ name: 'endTime', type: 'uint256' },
{ name: 'zoneHash', type: 'bytes32' },
{ name: 'salt', type: 'uint256' },
{ name: 'offererConduitKey', type: 'bytes32' },
{ name: 'fulfillerConduitKey', type: 'bytes32' },
{ name: 'totalOriginalAdditionalRecipients', type: 'uint256' },
{ name: 'additionalRecipients', type: 'tuple[]', components: [
{ name: 'amount', type: 'uint256' },
{ name: 'recipient', type: 'address' }
]},
{ name: 'signature', type: 'bytes' }
]
}],
outputs: [{ name: 'fulfilled', type: 'bool' }]
}];
async function buyNFT(orderHash, chain, buyerAddress, privateKey) {
// 1. Get fulfillment data
const res = await fetch('https://api.opensea.io/api/v2/listings/fulfillment_data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.OPENSEA_API_KEY
},
body: JSON.stringify({
listing: { hash: orderHash, chain, protocol_address: '0x0000000000000068F116a894984e2DB1123eB395' },
fulfiller: { address: buyerAddress }
})
});
const { fulfillment_data } = await res.json();
const tx = fulfillment_data.transaction;
const params = tx.input_data.parameters;
// 2. Setup wallet
const account = privateKeyToAccount(privateKey);
const wallet = createWalletClient({ account, chain: base, transport: http() });
const pub = createPublicClient({ chain: base, transport: http() });
// 3. Encode and send
const orderParams = {
...params,
considerationIdentifier: BigInt(params.considerationIdentifier),
considerationAmount: BigInt(params.considerationAmount),
offerIdentifier: BigInt(params.offerIdentifier),
offerAmount: BigInt(params.offerAmount),
startTime: BigInt(params.startTime),
endTime: BigInt(params.endTime),
salt: BigInt(params.salt),
totalOriginalAdditionalRecipients: BigInt(params.totalOriginalAdditionalRecipients),
additionalRecipients: params.additionalRecipients.map(r => ({
amount: BigInt(r.amount),
recipient: r.recipient
}))
};
const data = encodeFunctionData({
abi: SEAPORT_ABI,
functionName: 'fulfillBasicOrder_efficient_6GL6yc',
args: [orderParams]
});
const hash = await wallet.sendTransaction({
to: tx.to,
data,
value: BigInt(tx.value)
});
console.log(`TX: https://basescan.org/tx/${hash}`);
const receipt = await pub.waitForTransactionReceipt({ hash });
return receipt.status === 'success';
}
```
---
## Selling NFTs (Accepting Offers)
Similar workflow using `/api/v2/offers/fulfillment_data`:
```bash
./scripts/opensea-fulfill-offer.sh base 0xOFFER_HASH 0xYOUR_WALLET 0xNFT_CONTRACT 1234
```
---
## Creating Listings
Creating listings requires signing a Seaport order:
1. Build order structure with offer (your NFT) and consideration (payment)
2. Sign order with EIP-712
3. POST signed order to OpenSea
See `references/marketplace-api.md` for full order structure.
---
## Key Points
- **Fulfillment API returns ready-to-use calldata** - No SDK needed for buying
- **Value field** tells you exactly how much ETH to send
- **Works on all EVM chains** OpenSea supports
- **Basic orders** use `fulfillBasicOrder_efficient_6GL6yc` function
- **Advanced orders** use `fulfillAvailableAdvancedOrders` for partial fills
```
### references/token-swaps.md
```markdown
# Token Swaps via OpenSea MCP
OpenSea MCP provides token swap functionality through integrated DEX aggregation. This allows swapping ERC20 tokens and native currencies across supported chains.
## Overview
The `get_token_swap_quote` tool returns:
1. **Quote details** - Expected output, fees, price impact
2. **Transaction calldata** - Ready to submit on-chain
## Supported Chains
- Ethereum (`ethereum`)
- Base (`base`)
- Polygon (`matic`)
- Arbitrum (`arbitrum`)
- Optimism (`optimism`)
## Getting a Swap Quote
### Via mcporter CLI
```bash
mcporter call opensea.get_token_swap_quote --args '{
"fromContractAddress": "0x0000000000000000000000000000000000000000",
"fromChain": "base",
"toContractAddress": "0xb695559b26bb2c9703ef1935c37aeae9526bab07",
"toChain": "base",
"fromQuantity": "0.02",
"address": "0xYourWalletAddress"
}'
```
### Parameters
| Parameter | Required | Description |
|-----------|----------|-------------|
| `fromContractAddress` | Yes | Token to swap FROM. Use `0x0000...0000` for native ETH |
| `toContractAddress` | Yes | Token to swap TO |
| `fromChain` | Yes | Source chain identifier |
| `toChain` | Yes | Destination chain identifier |
| `fromQuantity` | Yes | Amount in human units (e.g., "0.02" for 0.02 ETH) |
| `address` | Yes | Your wallet address |
| `recipient` | No | Recipient address (defaults to sender) |
| `slippageTolerance` | No | Slippage as decimal (e.g., 0.005 for 0.5%) |
### Response Structure
```json
{
"swapQuote": {
"swapRoutes": [{
"toAsset": { "symbol": "MOLT", "usdPrice": "0.00045" },
"fromAsset": { "symbol": "ETH", "usdPrice": "2370" },
"costs": [
{ "costType": "GAS", "cost": { "usd": 0.01 } },
{ "costType": "MARKETPLACE", "cost": { "usd": 0.40 } }
],
"swapImpact": { "percent": "3.5" }
}],
"totalPrice": { "usd": 47.40 }
},
"swap": {
"actions": [{
"transactionSubmissionData": {
"to": "0xSwapRouterContract",
"data": "0x...",
"value": "20000000000000000",
"chain": { "networkId": 8453, "identifier": "base" }
}
}]
}
}
```
## Executing the Swap
### Using viem (JavaScript)
```javascript
import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
// Get quote first (via mcporter or direct API call)
const quote = await getSwapQuote(...);
const txData = quote.swap.actions[0].transactionSubmissionData;
// Setup wallet
const account = privateKeyToAccount(PRIVATE_KEY);
const wallet = createWalletClient({ account, chain: base, transport: http() });
const pub = createPublicClient({ chain: base, transport: http() });
// Execute swap
const hash = await wallet.sendTransaction({
to: txData.to,
data: txData.data,
value: BigInt(txData.value)
});
console.log(`TX: https://basescan.org/tx/${hash}`);
// Wait for confirmation
const receipt = await pub.waitForTransactionReceipt({ hash });
console.log(receipt.status === 'success' ? '✅ Swap complete!' : '❌ Failed');
```
### Using the swap script
```bash
./scripts/opensea-swap.sh <to_token_address> <amount_eth> <your_wallet> <private_key>
# Example: Swap 0.02 ETH to MOLT
./scripts/opensea-swap.sh 0xb695559b26bb2c9703ef1935c37aeae9526bab07 0.02 0xYourWallet 0xYourPrivateKey
```
## Finding Tokens
### Search by name
```bash
mcporter call opensea.search_tokens --args '{"query": "MOLT", "chain": "base", "limit": 5}'
```
### Get trending tokens
```bash
mcporter call opensea.get_trending_tokens --args '{"chains": ["base"], "limit": 10}'
```
### Get top tokens by volume
```bash
mcporter call opensea.get_top_tokens --args '{"chains": ["base"], "limit": 10}'
```
## Checking Balances
```bash
mcporter call opensea.get_token_balances --args '{
"address": "0xYourWallet",
"chains": ["base", "ethereum"]
}'
```
## Common Token Addresses (Base)
| Token | Address |
|-------|---------|
| WETH | `0x4200000000000000000000000000000000000006` |
| USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| MOLT | `0xb695559b26bb2c9703ef1935c37aeae9526bab07` |
| CLAWD | `0x9f86db9fc6f7c9408e8fda3ff8ce4e78ac7a6b07` |
| 4CLAW | `0x3b94a3fa7f33930cf9fdc5f36cb251533c947b07` |
## Tips
1. **Use native ETH address** (`0x0000...0000`) when swapping from ETH
2. **Check slippage** - High impact swaps may fail; consider smaller amounts
3. **Quote expiration** - Execute quickly after getting quote; prices change
4. **Gas estimation** - The returned value includes all costs
5. **Cross-chain swaps** - Same-chain swaps are faster and cheaper
```
---
## Skill Companion Files
> Additional files collected from the skill directory layout.
### README.md
```markdown
# OpenSea Skill
**Query NFT data, trade on the Seaport marketplace, and swap ERC20 tokens** across Ethereum, Base, Arbitrum, Optimism, Polygon, and more.
## What is this?
This is an [Agent Skill](https://skills.sh/docs) for AI coding assistants. Once installed, your agent can interact with the OpenSea API to query NFT data, execute marketplace operations, and swap ERC20 tokens using the [OpenSea CLI](https://github.com/ProjectOpenSea/opensea-cli), shell scripts, or the MCP server.
## Prerequisites
- `OPENSEA_API_KEY` environment variable — for CLI, SDK, and REST API scripts
- `OPENSEA_MCP_TOKEN` environment variable — for the MCP server (separate from API key)
- Node.js >= 18.0.0 — for `@opensea/cli`
- `curl` for REST shell scripts
- `jq` (recommended) for parsing JSON responses
Get both credentials at [opensea.io/settings/developer](https://opensea.io/settings/developer).
## Installing the Skill
### Using npx
```bash
npx skills add ProjectOpenSea/opensea-skill
```
### Using Claude Code
```bash
/skill install ProjectOpenSea/opensea-skill
```
### Manual Installation
Clone this repository to your skills directory:
```bash
git clone https://github.com/ProjectOpenSea/opensea-skill.git ~/.skills/opensea
```
Refer to your AI tool's documentation for skills directory configuration.
## What's Included
### Skill Definition
[`SKILL.md`](SKILL.md) — the main skill file that teaches your agent how to use the OpenSea API, including the CLI, task guides, script references, MCP tool documentation, and end-to-end workflows for buying, selling, and swapping tokens.
### OpenSea CLI (Recommended)
The [`@opensea/cli`](https://github.com/ProjectOpenSea/opensea-cli) package provides a command-line interface and programmatic SDK for all OpenSea API operations. Install with `npm install -g @opensea/cli` or use `npx @opensea/cli`.
```bash
opensea collections get mfers
opensea listings best mfers --limit 5
opensea tokens trending --limit 5
opensea search "cool cats"
opensea swaps quote --from-chain base --from-address 0x0000000000000000000000000000000000000000 \
--to-chain base --to-address 0xTokenAddress --quantity 0.02 --address 0xYourWallet
```
Supports JSON, table, and [TOON](https://github.com/toon-format/toon) output formats. TOON uses ~40% fewer tokens than JSON, ideal for AI agent context windows (`--format toon`).
See [`SKILL.md`](SKILL.md) for the full CLI command reference and SDK usage.
### Shell Scripts
Ready-to-use scripts in [`scripts/`](scripts/) for common operations (alternative to the CLI):
| Script | Purpose |
|--------|---------|
| `opensea-collection.sh` | Fetch collection by slug |
| `opensea-nft.sh` | Fetch single NFT by chain/contract/token |
| `opensea-best-listing.sh` | Get lowest listing for an NFT |
| `opensea-best-offer.sh` | Get highest offer for an NFT |
| `opensea-swap.sh` | Swap tokens via OpenSea DEX aggregator |
| `opensea-fulfill-listing.sh` | Get buy transaction data |
| `opensea-fulfill-offer.sh` | Get sell transaction data |
See [`SKILL.md`](SKILL.md) for the full scripts reference and usage examples.
### Reference Docs
Detailed API documentation in [`references/`](references/):
- [`rest-api.md`](references/rest-api.md) — REST endpoint families and pagination
- [`marketplace-api.md`](references/marketplace-api.md) — Buy/sell workflows and Seaport details
- [`stream-api.md`](references/stream-api.md) — WebSocket event streaming
- [`seaport.md`](references/seaport.md) — Seaport protocol and NFT purchase execution
- [`token-swaps.md`](references/token-swaps.md) — Token swap workflows via MCP
## OpenSea MCP Server
An official MCP server provides direct LLM integration for token swaps and NFT operations. Add to your MCP config:
```json
{
"mcpServers": {
"opensea": {
"url": "https://mcp.opensea.io/mcp",
"headers": {
"Authorization": "Bearer YOUR_MCP_TOKEN"
}
}
}
}
```
See [`SKILL.md`](SKILL.md) for the full list of available MCP tools.
## Example Usage
Once installed, prompt your AI assistant:
```
Get me the floor price for the Pudgy Penguins collection on OpenSea
```
```
Swap 0.02 ETH to USDC on Base using OpenSea
```
```
Show me the best offer on BAYC #1234
```
The agent will use the `opensea` CLI to query the API directly.
## Supported Chains
This skill supports all chains available on OpenSea, including `ethereum`, `solana`, `abstract`, `ape_chain`, `arbitrum`, `avalanche`, `b3`, `base`, `bera_chain`, `blast`, `flow`, `gunzilla`, `hyperevm`, `hyperliquid`, `ink`, `megaeth`, `monad`, `optimism`, `polygon`, `ronin`, `sei`, `shape`, `somnia`, `soneium`, `unichain`, and `zora`.
## Learn More
- [OpenSea CLI](https://github.com/ProjectOpenSea/opensea-cli) — CLI and SDK for OpenSea API
- [OpenSea Developer Docs](https://docs.opensea.io/)
- [OpenSea Developer Portal](https://opensea.io/settings/developer)
- [Agent Skills Directory](https://skills.sh/docs)
```
### _meta.json
```json
{
"owner": "dfinzer",
"slug": "opensea-skill",
"displayName": "OpenSea",
"latest": {
"version": "1.0.3",
"publishedAt": 1772352161109,
"commit": "https://github.com/openclaw/skills/commit/1beb15cc2e21b63d72520b2f205a616a3949348e"
},
"history": []
}
```
### scripts/opensea-account-nfts.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 2 ]; then
echo "Usage: opensea-account-nfts.sh <chain> <wallet_address> [limit] [next]" >&2
exit 1
fi
chain="$1"
address="$2"
limit="${3-}"
next="${4-}"
query=""
if [ -n "$limit" ]; then
query="limit=$limit"
fi
if [ -n "$next" ]; then
if [ -n "$query" ]; then
query="$query&next=$next"
else
query="next=$next"
fi
fi
"$(dirname "$0")/opensea-get.sh" "/api/v2/chain/${chain}/account/${address}/nfts" "$query"
```
### scripts/opensea-collection-nfts.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 1 ]; then
echo "Usage: opensea-collection-nfts.sh <collection_slug> [limit] [next]" >&2
exit 1
fi
slug="$1"
limit="${2-}"
next="${3-}"
query=""
if [ -n "$limit" ]; then
query="limit=$limit"
fi
if [ -n "$next" ]; then
if [ -n "$query" ]; then
query="$query&next=$next"
else
query="next=$next"
fi
fi
"$(dirname "$0")/opensea-get.sh" "/api/v2/collection/${slug}/nfts" "$query"
```
### scripts/opensea-collection-stats.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 1 ]; then
echo "Usage: opensea-collection-stats.sh <collection_slug>" >&2
echo "Example: opensea-collection-stats.sh boredapeyachtclub" >&2
exit 1
fi
slug="$1"
"$(dirname "$0")/opensea-get.sh" "/api/v2/collections/${slug}/stats"
```
### scripts/opensea-collection.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 1 ]; then
echo "Usage: opensea-collection.sh <collection_slug>" >&2
exit 1
fi
slug="$1"
"$(dirname "$0")/opensea-get.sh" "/api/v2/collections/${slug}"
```
### scripts/opensea-events-collection.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 1 ]; then
echo "Usage: opensea-events-collection.sh <collection_slug> [event_type] [limit] [next]" >&2
exit 1
fi
slug="$1"
event_type="${2-}"
limit="${3-}"
next="${4-}"
query=""
if [ -n "$event_type" ]; then
query="event_type=$event_type"
fi
if [ -n "$limit" ]; then
if [ -n "$query" ]; then
query="$query&limit=$limit"
else
query="limit=$limit"
fi
fi
if [ -n "$next" ]; then
if [ -n "$query" ]; then
query="$query&next=$next"
else
query="next=$next"
fi
fi
"$(dirname "$0")/opensea-get.sh" "/api/v2/events/collection/${slug}" "$query"
```
### scripts/opensea-get.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 1 ]; then
echo "Usage: opensea-get.sh <path> [query]" >&2
echo "Example: opensea-get.sh /api/v2/collections/cool-cats-nft" >&2
exit 1
fi
path="$1"
query="${2-}"
base="${OPENSEA_BASE_URL:-https://api.opensea.io}"
key="${OPENSEA_API_KEY:-}"
if [ -z "$key" ]; then
echo "OPENSEA_API_KEY is required" >&2
exit 1
fi
url="$base$path"
if [ -n "$query" ]; then
url="$url?$query"
fi
curl -sS -H "x-api-key: $key" "$url"
```
### scripts/opensea-listings-collection.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 1 ]; then
echo "Usage: opensea-listings-collection.sh <collection_slug> [limit] [next]" >&2
exit 1
fi
slug="$1"
limit="${2-}"
next="${3-}"
query=""
if [ -n "$limit" ]; then
query="limit=$limit"
fi
if [ -n "$next" ]; then
if [ -n "$query" ]; then
query="$query&next=$next"
else
query="next=$next"
fi
fi
"$(dirname "$0")/opensea-get.sh" "/api/v2/listings/collection/${slug}/all" "$query"
```
### scripts/opensea-listings-nft.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 3 ]; then
echo "Usage: opensea-listings-nft.sh <chain> <contract_address> <token_id> [limit]" >&2
echo "Example: opensea-listings-nft.sh ethereum 0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d 1234" >&2
exit 1
fi
chain="$1"
contract="$2"
token_id="$3"
limit="${4:-50}"
"$(dirname "$0")/opensea-get.sh" "/api/v2/orders/${chain}/seaport/listings" "asset_contract_address=${contract}&token_ids=${token_id}&limit=${limit}"
```
### scripts/opensea-nft.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 3 ]; then
echo "Usage: opensea-nft.sh <chain> <contract_address> <token_id>" >&2
exit 1
fi
chain="$1"
contract="$2"
token_id="$3"
"$(dirname "$0")/opensea-get.sh" "/api/v2/chain/${chain}/contract/${contract}/nfts/${token_id}"
```
### scripts/opensea-offers-collection.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 1 ]; then
echo "Usage: opensea-offers-collection.sh <collection_slug> [limit] [next]" >&2
exit 1
fi
slug="$1"
limit="${2-}"
next="${3-}"
query=""
if [ -n "$limit" ]; then
query="limit=$limit"
fi
if [ -n "$next" ]; then
if [ -n "$query" ]; then
query="$query&next=$next"
else
query="next=$next"
fi
fi
"$(dirname "$0")/opensea-get.sh" "/api/v2/offers/collection/${slug}/all" "$query"
```
### scripts/opensea-offers-nft.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 3 ]; then
echo "Usage: opensea-offers-nft.sh <chain> <contract_address> <token_id> [limit]" >&2
echo "Example: opensea-offers-nft.sh ethereum 0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d 1234" >&2
exit 1
fi
chain="$1"
contract="$2"
token_id="$3"
limit="${4:-50}"
"$(dirname "$0")/opensea-get.sh" "/api/v2/orders/${chain}/seaport/offers" "asset_contract_address=${contract}&token_ids=${token_id}&limit=${limit}"
```
### scripts/opensea-order.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -ne 2 ]; then
echo "Usage: opensea-order.sh <chain> <order_hash>" >&2
echo "Example: opensea-order.sh ethereum 0x1234..." >&2
exit 1
fi
chain="$1"
order_hash="$2"
protocol="0x0000000000000068f116a894984e2db1123eb395"
"$(dirname "$0")/opensea-get.sh" "/api/v2/orders/chain/${chain}/protocol/${protocol}/${order_hash}"
```
### scripts/opensea-post.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 2 ]; then
echo "Usage: opensea-post.sh <path> <json_body>" >&2
echo "Example: opensea-post.sh /api/v2/listings/fulfillment_data '{\"listing\":{...}}'" >&2
exit 1
fi
path="$1"
body="$2"
base="${OPENSEA_BASE_URL:-https://api.opensea.io}"
key="${OPENSEA_API_KEY:-}"
if [ -z "$key" ]; then
echo "OPENSEA_API_KEY is required" >&2
exit 1
fi
url="$base$path"
curl -sS -X POST \
-H "x-api-key: $key" \
-H "Content-Type: application/json" \
-d "$body" \
"$url"
```
### scripts/opensea-stream-collection.sh
```bash
#!/usr/bin/env bash
set -euo pipefail
if [ "$#" -lt 1 ]; then
echo "Usage: opensea-stream-collection.sh <collection_slug|*>" >&2
exit 1
fi
slug="$1"
key="${OPENSEA_API_KEY:-}"
if [ -z "$key" ]; then
echo "OPENSEA_API_KEY is required" >&2
exit 1
fi
url="wss://stream.openseabeta.com/socket/websocket?token=${key}"
join="{\"topic\":\"collection:${slug}\",\"event\":\"phx_join\",\"payload\":{},\"ref\":1}"
heartbeat="{\"topic\":\"phoenix\",\"event\":\"heartbeat\",\"payload\":{},\"ref\":0}"
if command -v websocat >/dev/null 2>&1; then
{
printf '%s\n' "$join"
while sleep 30; do
printf '%s\n' "$heartbeat"
done
} | websocat -t "$url"
exit 0
fi
if command -v wscat >/dev/null 2>&1; then
cat <<INFO
wscat is installed, but it does not auto-send join/heartbeat.
Run: wscat -c "$url"
Then send:
$join
And every ~30s:
$heartbeat
INFO
exit 0
fi
echo "Install websocat (preferred) or wscat to use the Stream API." >&2
exit 1
```
### scripts/opensea-swap.sh
```bash
#!/bin/bash
# Swap tokens via OpenSea MCP
# Usage: PRIVATE_KEY=0xYourKey ./opensea-swap.sh <to_token_address> <amount> <wallet_address> [chain] [from_token]
#
# Example:
# PRIVATE_KEY=0xYourKey ./opensea-swap.sh 0xb695559b26bb2c9703ef1935c37aeae9526bab07 0.02 0xYourWallet base
# PRIVATE_KEY=0xYourKey ./opensea-swap.sh 0xToToken 100 0xYourWallet base 0xFromToken
#
# Requires: OPENSEA_API_KEY env var, PRIVATE_KEY env var, mcporter, node with viem
TO_TOKEN="${1:?Usage: PRIVATE_KEY=0x... $0 <to_token_address> <amount> <wallet_address> [chain] [from_token]}"
AMOUNT="${2:?Amount required}"
WALLET="${3:?Wallet address required}"
CHAIN="${4:-base}"
FROM_TOKEN="${5:-0x0000000000000000000000000000000000000000}"
if [ -z "$PRIVATE_KEY" ]; then
echo "❌ PRIVATE_KEY environment variable is required"
exit 1
fi
echo "🔄 Getting swap quote: ${AMOUNT} tokens → token on ${CHAIN}..."
# Get swap quote via mcporter
QUOTE=$(mcporter call opensea.get_token_swap_quote --args "{
\"fromContractAddress\": \"${FROM_TOKEN}\",
\"fromChain\": \"${CHAIN}\",
\"toContractAddress\": \"${TO_TOKEN}\",
\"toChain\": \"${CHAIN}\",
\"fromQuantity\": \"${AMOUNT}\",
\"address\": \"${WALLET}\"
}" --output raw 2>&1)
if echo "$QUOTE" | grep -q "error"; then
echo "❌ Failed to get quote: $QUOTE"
exit 1
fi
# Save quote for parsing
echo "$QUOTE" > /tmp/opensea_swap_quote.json
# Execute with node
node --input-type=module -e "
import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base, mainnet, polygon, arbitrum, optimism } from 'viem/chains';
import { readFileSync } from 'fs';
const chains = { base, ethereum: mainnet, mainnet, matic: polygon, polygon, arbitrum, optimism };
const chain = chains['${CHAIN}'] || base;
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const wallet = createWalletClient({ account, chain, transport: http() });
const pub = createPublicClient({ chain, transport: http() });
// Parse the mcporter output (wrapped in content structure)
const raw = readFileSync('/tmp/opensea_swap_quote.json', 'utf8');
let quote;
try {
const wrapper = JSON.parse(raw);
quote = JSON.parse(wrapper.content[0].text);
} catch (e) {
quote = JSON.parse(raw);
}
const txData = quote.swap.actions[0].transactionSubmissionData;
const toSymbol = quote.swapQuote.swapRoutes[0].toAsset.symbol;
console.log('📊 Quote received');
console.log(' To:', txData.to);
console.log(' Value:', txData.value, 'wei');
console.log(' Token:', toSymbol);
console.log('📤 Sending transaction...');
const hash = await wallet.sendTransaction({
to: txData.to,
data: txData.data,
value: BigInt(txData.value)
});
console.log('TX: https://basescan.org/tx/' + hash);
console.log('⏳ Waiting for confirmation...');
const receipt = await pub.waitForTransactionReceipt({ hash });
console.log(receipt.status === 'success' ? '✅ Swap complete!' : '❌ Swap failed');
console.log('Gas used:', receipt.gasUsed.toString());
"
```