Cancel Offer
There are two ways to cancel an offer: Gasless (Off-chain) and Secure (On-chain).
- Gasless Cancel (Off-chain): Removes the offer from our database using an EIP-191 signature. This is free and fast, but the signed offer remains technically valid on-chain if a seller possesses the original signature and calls the exchange contract.
- Secure Cancel (On-chain): Submits a transaction calling the exchange contract directly to cryptographically invalidate the order nonce. This requires a gas fee but guarantees the offer can never be fulfilled on-chain.
Secure Cancel (On-chain) — Recommended for safety
To completely invalidate the order on-chain, the buyer submits a transaction to the MintpadExchange contract.
Step 1 — Obtain the offer's nonce
Query GET /v1/offers (requires x-api-key) to retrieve the offer's nonce string.
Step 2 — Submit the contract transaction
Call the cancelMultipleMakerOrders function on the MintpadExchange contract from the user's wallet:
- Exchange Address:
0xdFbE43b2c154B6a790158fa2696cDb32A86Efc78 - Function:
cancelMultipleMakerOrders(uint256[] nonces)
// ethers.js v6const exchange = new Contract(EXCHANGE_ADDRESS, MINTPAD_EXCHANGE_ABI, signer)const tx = await exchange.cancelMultipleMakerOrders([BigInt(nonce)])await tx.wait()Step 3 — Sync with the Database
After the transaction is confirmed on-chain, call the off-chain DELETE request (see below) to remove the offer from the database index.
Gasless Cancel (Off-chain)
To remove the offer from the marketplace without paying gas, have the buyer sign a cancellation message and send it to the partner API.
Step 1 — Obtain the orderHash
The orderHash is the unique identifier for an offer. You need it to identify which offer to cancel.
Option A — Store it at creation time. The POST /v1/offers response always includes it:
{ "success": true, "orderHash": "0xabcde12345...", "status": "active"}Option B — Look it up by querying the active offer. Use GET /v1/offers (requires x-api-key) filtered by collection and buyer:
GET /v1/offers?collectionAddress=0x29ef...&buyer=0x9876...The orderHash field is present on every offer object in the response:
{ "offers": [ { "orderHash": "0xabcde12345...", "tokenId": null, "buyer": "0x9876543210abcdef9876543210abcdef98765432", "priceWei": "100000000000000000000", "nonce": "1718274092" } ]}Step 2 — Sign the Cancellation Message
The buyer must sign an EIP-191 personal_sign message — not a typed data signature. The message is a plain string:
Cancel Mintpad Offer: <orderHash>Where <orderHash> is the full lowercase hex string (e.g. 0xabcde12345...).
// ethers.js v6const message = `Cancel Mintpad Offer: ${orderHash}`const signature = await signer.signMessage(message)// viemconst signature = await walletClient.signMessage({ account: buyerAddress, message: `Cancel Mintpad Offer: ${orderHash}`})The message format must be exact — including the colon and space before the hash. The API will reject signatures with any variation in the string.
Step 3 — Send the Cancel Request
DELETE /v1/offers/:orderHash
Headers:
x-api-key:mp_part_yourkey
{ "signature": "0xsignaturehex..."}Offer Ownership Requirement
A partner can only cancel offers that were created using their own API key. If the offer was created by another partner or directly on the Mintpad website, the API will reject the request with 403 Forbidden.
The API recovers the signer from the signature and verifies:
- The signature matches the original offer's
signeraddress. - The offer was originally created by the requesting partner (
partnerIdmatches the authenticated API key).
If all checks pass, the offer is marked as cancelled immediately.
Error Responses
If the offer was created by another partner:
- Status:
403 Forbidden - Body:
{ "error": "FORBIDDEN", "message": "This offer was not created by your partner account." }Response
{ "success": true, "orderHash": "0xabcde12345...", "status": "cancelled"}Full Example (Gasless)
async function cancelOffer( orderHash: string, buyerAddress: string, signer: Signer, // ethers.js v6 apiKey: string) { // 1. Sign the cancellation message const message = `Cancel Mintpad Offer: ${orderHash}` const signature = await signer.signMessage(message) // 2. Submit the cancel request const res = await fetch( `https://partners-api.mintpad.app/v1/offers/${orderHash}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify({ signature }) } ) const data = await res.json() if (!data.success) throw new Error(`Cancel failed: ${data.error}`) return data}