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

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 viem
import { 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 ready

Bulk 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(
  "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC", // Seaport protocol address
  "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/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC/0xORDER_HASH/cancel" \
  -H "X-API-KEY: YOUR_API_KEY"

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