Collection offers and advanced trading
Use collection offers, trait offers, bulk operations, and advanced order management.
The OpenSea SDK (@opensea/sdk) supports trading patterns beyond single-item listings and offers. This guide covers collection offers, trait offers, bulk operations, order cancellation, private orders, and WETH management.
Prerequisites
- Node.js >= 20.0.0
- OpenSea API key (get one here, or use the instant API key endpoint)
- viem (v2+). ethers.js (v6+) is also supported.
- A funded wallet with WETH (for offers)
Security Warning: Do not use the SDK in client-side code, since your API key would be exposed. Use it on a backend server and return transaction data to your frontend.
Setup
npm install @opensea/sdk viemimport { createPublicClient, createWalletClient, http } from "viem";
import { mainnet } from "viem/chains";
import { OpenSeaSDK, Chain } from "@opensea/sdk/viem";
const publicClient = createPublicClient({ chain: mainnet, transport: http("https://your-rpc-url") });
const walletClient = createWalletClient({ chain: mainnet, transport: http("https://your-rpc-url"), account: "0x..." });
const sdk = new OpenSeaSDK(
{ publicClient, walletClient },
{ chain: Chain.Mainnet, apiKey: "YOUR_API_KEY" },
);The examples below use viem. The SDK also supports ethers.js (v6+); see Buy and sell NFTs for the ethers setup. All SDK methods work the same with either library.
Collection-wide offers
A collection offer applies to any NFT in a collection. The first holder to accept it fulfills the order.
SDK
const collectionOffer = await sdk.createCollectionOffer({
collectionSlug: "boredapeyachtclub",
accountAddress: "0xYOUR_WALLET_ADDRESS",
amount: 5,
quantity: 1,
});
console.log("Collection offer created:", collectionOffer);curl
Collection offers use the Seaport protocol. Use sdk.api.buildOffer() to generate the order parameters, then post:
curl -X POST "https://api.opensea.io/api/v2/orders/ethereum/seaport/offers" \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"parameters": { ... },
"protocol_address": "0x...",
"signature": "0x..."
}'Trait-based offers
Make an offer on all NFTs in a collection that share a specific trait, for example all Bored Apes with a "Gold" background.
const traitOffer = await sdk.createCollectionOffer({
collectionSlug: "boredapeyachtclub",
accountAddress: "0xYOUR_WALLET_ADDRESS",
amount: 8,
quantity: 1,
traitType: "Background",
traitValue: "Gold",
});
console.log("Trait offer created:", traitOffer);Building offers before posting
Use sdk.api.buildOffer() to construct the order parameters without submitting. This is useful for previewing or modifying the order before signing.
const buildResponse = await sdk.api.buildOffer({
offerer: "0xYOUR_WALLET_ADDRESS",
quantity: 1,
collectionSlug: "boredapeyachtclub",
});
console.log("Order parameters:", buildResponse);
// Sign and submit when readyBulk listings
List multiple NFTs in a single operation:
const listings = await sdk.createBulkListings({
listings: [
{
asset: { tokenAddress: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", tokenId: "1234" },
accountAddress: "0xYOUR_WALLET_ADDRESS",
amount: 10,
},
{
asset: { tokenAddress: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", tokenId: "5678" },
accountAddress: "0xYOUR_WALLET_ADDRESS",
amount: 12,
},
],
});
console.log("Bulk listings created:", listings);Bulk offers
Make offers on multiple items at once:
const offers = await sdk.createBulkOffers({
offers: [
{
asset: { tokenAddress: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", tokenId: "1234" },
accountAddress: "0xYOUR_WALLET_ADDRESS",
amount: 5,
},
{
asset: { tokenAddress: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", tokenId: "5678" },
accountAddress: "0xYOUR_WALLET_ADDRESS",
amount: 6,
},
],
});
console.log("Bulk offers created:", offers);Canceling orders
On-chain cancellation
Permanently cancels an order on the blockchain. Costs gas but is immediate and irreversible.
const txHash = await sdk.cancelOrder({
order,
accountAddress: "0xYOUR_WALLET_ADDRESS",
});
console.log("Cancelled onchain:", txHash);Off-chain (gas-free) cancellation
Cancels an order through OpenSea's off-chain system. No gas cost, but relies on OpenSea's order book.
await sdk.offchainCancelOrder(
"0x0000000000000068F116a894984e2DB1123eB395", // Seaport 1.6
"0xORDER_HASH",
Chain.Mainnet,
);
console.log("Cancelled off-chain");curl (off-chain)
curl -X POST "https://api.opensea.io/api/v2/orders/chain/ethereum/protocol/0x0000000000000068F116a894984e2DB1123eB395/0xORDER_HASH/cancel" \
-H "X-API-KEY: YOUR_API_KEY"An order is identified by chain, protocol address, and order hash together, so the protocol address has to be the one the order was created on. New OpenSea orders use Seaport 1.6 (0x0000000000000068F116a894984e2DB1123eB395); older ones may still be on Seaport 1.5 (0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC). Pass the protocol_address from the order itself when you have it.
Fulfilling private orders
Private (exclusive) orders are restricted to a specific buyer address. Fulfill them with:
await sdk.fulfillPrivateOrder({
order,
accountAddress: "0xBUYER_WALLET_ADDRESS",
});Checking order fulfillability
Before attempting to fulfill an order, verify it's still valid:
const canFulfill = await sdk.isOrderFulfillable({
order,
accountAddress: "0xYOUR_WALLET_ADDRESS",
});
if (canFulfill) {
await sdk.fulfillOrder({ order, accountAddress: "0xYOUR_WALLET_ADDRESS" });
} else {
console.log("Order is no longer fulfillable");
}Wrapping and unwrapping ETH
Offers on OpenSea require WETH (Wrapped ETH). The SDK provides helpers:
Wrap ETH to WETH
await sdk.wrapEth({
amountInEth: 1.5,
accountAddress: "0xYOUR_WALLET_ADDRESS",
});Unwrap WETH to ETH
await sdk.unwrapWeth({
amountInEth: 1.5,
accountAddress: "0xYOUR_WALLET_ADDRESS",
});Next steps
- Buy and sell NFTs: single-item listings, offers, and fulfillment
- Stream real-time events: react to marketplace events in real time
- Query analytics and events: track sales and order history
- @opensea/sdk on GitHub
- buy-sell-opensea-sdk-demo
Updated 19 days ago
