This reference covers the marketplace endpoints for buying and selling NFTs and tokens on OpenSea.
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: https://api.opensea.io/api/v2
Auth: x-api-key: $OPENSEA_API_KEY
| Chain | Identifier |
|---|---|
| Ethereum | ethereum |
| Polygon | matic |
| Arbitrum | arbitrum |
| Optimism | optimism |
| Base | base |
| Avalanche | avalanche |
| Klaytn | klaytn |
| Zora | zora |
| Blast | blast |
| Sepolia (testnet) | sepolia |
Returns the lowest-priced active listing for an NFT.
GET /api/v2/listings/collection/{collection_slug}/nfts/{identifier}/bestParameters:
collection_slug: Collection slug (e.g.,boredapeyachtclub)identifier: NFT identifier (token ID)
Example:
scripts/opensea-get.sh "/api/v2/listings/collection/boredapeyachtclub/nfts/1234/best"Returns the highest active offer for an NFT.
GET /api/v2/offers/collection/{collection_slug}/nfts/{identifier}/bestExample:
scripts/opensea-get.sh "/api/v2/offers/collection/boredapeyachtclub/nfts/1234/best"Returns all active listings for a collection.
GET /api/v2/listings/collection/{collection_slug}/allQuery parameters:
limit: Page size (default 50, max 100)next: Cursor for pagination
Example:
scripts/opensea-listings-collection.sh boredapeyachtclub 50Returns all active offers for a collection.
GET /api/v2/offers/collection/{collection_slug}/allExample:
scripts/opensea-offers-collection.sh boredapeyachtclub 50GET /api/v2/orders/{chain}/seaport/listingsQuery parameters:
asset_contract_address: Contract addresstoken_ids: Comma-separated token IDslimit,next: Pagination
Example:
scripts/opensea-get.sh "/api/v2/orders/ethereum/seaport/listings" "asset_contract_address=0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&token_ids=1234"GET /api/v2/orders/{chain}/seaport/offersQuery parameters:
asset_contract_address: Contract addresstoken_ids: Comma-separated token IDs
Example:
scripts/opensea-get.sh "/api/v2/orders/ethereum/seaport/offers" "asset_contract_address=0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&token_ids=1234"Retrieve details of a specific order.
GET /api/v2/orders/chain/{chain}/protocol/{protocol_address}/{order_hash}Example:
scripts/opensea-get.sh "/api/v2/orders/chain/ethereum/protocol/0x0000000000000068f116a894984e2db1123eb395/0x..."Creates an unsigned Seaport listing order. Returns order parameters to sign.
POST /api/v2/orders/{chain}/seaport/listingsRequest body:
{
"protocol_address": "0x0000000000000068f116a894984e2db1123eb395",
"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": "24446860302761739304752683030156737591518664810215442929805094493721949474548",
"conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
"totalOriginalConsiderationItems": 1,
"counter": "0"
},
"signature": "0xSignedOrderSignature"
}Required top-level fields: protocol_address, parameters, signature.
Required parameters fields (all must be present before signing): offerer, zone, offer, consideration, startTime, endTime, orderType, zoneHash, salt, conduitKey, totalOriginalConsiderationItems, counter.
Field notes:
counter— Seaport nonce for the offerer. Fetch withgetCounter(address)on the Seaport contract, or use"0"for accounts that have never canceled viaincrementCounter. Order hashes and EIP-712 signatures are bound to this value.salt— uint256 as a decimal string (e.g. fromtoString(randomBigInt(256))). A hex string works too as long as it parses as uint256.conduitKey—0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000is OpenSea's conduit. Use0x0000…0000to transfer directly without a conduit.zone/zoneHash— use zero address / zero bytes32 unless you're integrating a custom zone.zoneis part of the signedOrderComponentsstruct, so it must be present inparameters(even as the zero address) or signing will fail.- See
### Signing Orders (EIP-712)below for building the signature.
Item Types:
0: Native currency (ETH, MATIC, etc.)1: ERC20 token2: ERC721 NFT3: ERC1155 NFT
Example (curl):
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 '{"protocol_address": "0x0000000000000068f116a894984e2db1123eb395", "parameters": {...}, "signature": "0x..."}'Creates an unsigned Seaport offer order.
POST /api/v2/orders/{chain}/seaport/offersRequest body structure (same shape as listings — top-level protocol_address, parameters, signature — but offer contains payment and consideration contains the NFT):
{
"protocol_address": "0x0000000000000068f116a894984e2db1123eb395",
"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"
}],
"startTime": "1704067200",
"endTime": "1735689600",
"orderType": 0,
"zone": "0x0000000000000000000000000000000000000000",
"zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"salt": "24446860302761739304752683030156737591518664810215442929805094493721949474548",
"conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
"totalOriginalConsiderationItems": 1,
"counter": "0"
},
"signature": "0x..."
}Field requirements and notes are identical to Build a Listing — see above.
Both listing and offer creation require an EIP-712 signature over the order parameters. The signer must be the offerer.
Before signing, fetch the offerer's current Seaport counter:
# Returns the uint256 counter. Use "0" for any account that has never called incrementCounter.
cast call 0x0000000000000068F116a894984e2DB1123eB395 \
"getCounter(address)(uint256)" 0xYourWalletAddress \
--rpc-url <chain-rpc-url>EIP-712 domain:
{
"name": "Seaport",
"version": "1.6",
"chainId": 1,
"verifyingContract": "0x0000000000000068F116a894984e2DB1123eB395"
}Set chainId to the target chain ID (1 for Ethereum, 8453 for Base, 137 for Polygon, etc.). verifyingContract is the Seaport 1.6 address — the same value as protocol_address in the request body.
EIP-712 types (primary type OrderComponents):
{
"OrderComponents": [
{ "name": "offerer", "type": "address" },
{ "name": "zone", "type": "address" },
{ "name": "offer", "type": "OfferItem[]" },
{ "name": "consideration", "type": "ConsiderationItem[]" },
{ "name": "orderType", "type": "uint8" },
{ "name": "startTime", "type": "uint256" },
{ "name": "endTime", "type": "uint256" },
{ "name": "zoneHash", "type": "bytes32" },
{ "name": "salt", "type": "uint256" },
{ "name": "conduitKey", "type": "bytes32" },
{ "name": "counter", "type": "uint256" }
],
"OfferItem": [
{ "name": "itemType", "type": "uint8" },
{ "name": "token", "type": "address" },
{ "name": "identifierOrCriteria", "type": "uint256" },
{ "name": "startAmount", "type": "uint256" },
{ "name": "endAmount", "type": "uint256" }
],
"ConsiderationItem": [
{ "name": "itemType", "type": "uint8" },
{ "name": "token", "type": "address" },
{ "name": "identifierOrCriteria", "type": "uint256" },
{ "name": "startAmount", "type": "uint256" },
{ "name": "endAmount", "type": "uint256" },
{ "name": "recipient", "type": "address" }
]
}message: the parameters object from the request body, minus totalOriginalConsiderationItems (which is a submission-only field, not part of the signed struct). All uint256 values can stay as decimal strings; ethers/viem will coerce.
Example with viem:
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const client = createWalletClient({ account, transport: http() });
const { totalOriginalConsiderationItems, ...message } = parameters;
const signature = await client.signTypedData({
domain: {
name: 'Seaport',
version: '1.6',
chainId: 1,
verifyingContract: '0x0000000000000068F116a894984e2DB1123eB395',
},
types: { OrderComponents, OfferItem, ConsiderationItem },
primaryType: 'OrderComponents',
message,
});
// POST { protocol_address, parameters, signature } to /api/v2/orders/{chain}/seaport/listingsAfter signing, submit with protocol_address, the full parameters object (including totalOriginalConsiderationItems), and signature.
Accept an existing listing to purchase an NFT.
POST /api/v2/listings/fulfillment_dataRequest body:
{
"listing": {
"hash": "0xOrderHash",
"chain": "ethereum",
"protocol_address": "0x0000000000000068f116a894984e2db1123eb395"
},
"fulfiller": {
"address": "0xBuyerWalletAddress"
}
}Response: Returns transaction data for the buyer to submit onchain.
Accept an existing offer to sell your NFT.
POST /api/v2/offers/fulfillment_dataRequest body:
{
"offer": {
"hash": "0xOfferOrderHash",
"chain": "ethereum",
"protocol_address": "0x0000000000000068f116a894984e2db1123eb395"
},
"fulfiller": {
"address": "0xSellerWalletAddress"
},
"consideration": {
"asset_contract_address": "0xNFTContract",
"token_id": "1234"
}
}Cancel an active listing or offer.
POST /api/v2/orders/chain/{chain}/protocol/{protocol_address}/{order_hash}/cancelNote: Cancellation requires an onchain transaction. The API returns the transaction data to execute.
- Find the NFT - Use
opensea-nft.shto get NFT details - Check listings - Use
opensea-get.shto get best listing - Get fulfillment data - POST to
/api/v2/listings/fulfillment_data - Execute transaction - Sign and submit the returned transaction data
# 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- Build the listing - POST to
/api/v2/orders/{chain}/seaport/listings - Sign the order - Use wallet to sign the Seaport order
- Submit signed order - POST again with signature
- Monitor - Check listing via
/api/v2/listings/collection/{slug}/all
- Ensure WETH approval - Buyer needs WETH allowance for Seaport
- Build the offer - POST to
/api/v2/orders/{chain}/seaport/offers - Sign the order - Wallet signature required
- Submit - POST with signature
- View offers - Use
opensea-offers-collection.sh - Get fulfillment data - POST to
/api/v2/offers/fulfillment_data - Execute - Submit the returned transaction
| 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 apply per-account across all API keys. See references/rest-api.md for full details.
Default limits (Tier 1): 120 read/min, 60 write/min, 60 fulfillment/min
Fulfillment endpoints (/api/v2/listings/fulfillment_data, /api/v2/offers/fulfillment_data) use the fulfillment rate bucket. Order creation endpoints use the write rate bucket. All other GET endpoints use the read rate bucket.
| Chain | Seaport 1.6 Address |
|---|---|
| All chains | 0x0000000000000068F116a894984e2DB1123eB395 |
- Always use WETH for offers - Native ETH cannot be used for offers due to ERC20 approval requirements
- Check approval status - Before creating listings, ensure Seaport has approval for your NFTs
- Test on Sepolia first - Use testnet before mainnet transactions
- Handle expiration - Orders have startTime/endTime - check these before fulfilling
- Monitor events - Use Stream API for real-time order updates