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(
  "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