Partner dashboard
API contract v2

Partner API

Build carts from product URLs or live Collector Crypt cards, handle reviewed quotes as a normal asynchronous state, and pay server-authoritative orders in USDC.

Contract
Server-authoritative totals
Review
Asynchronous and resumable
Payment gate
`payment_ready` only

Authentication and authority

Keep credentials and all partner API calls on your server.

X-API-Key: sp3nd_...
X-API-Secret: sp3nd_sec_...
SP3ND resolves product facts and owns the final price, shipping, tax, fees, total, currency, payment memo, and recipient. Caller values are never payment authority.
Base URL
https://us-central1-sp3nddotshop-prod.cloudfunctions.net
schema_version
The response envelope is version 2 and additive; existing response fields remain available.
order_schema_version
New orders use 2; serialized legacy stored orders can report 1 inside the version 2 envelope.
payment_ready
The only supported signal that payment can begin.

Order lifecycle

A review state is a successful order creation, not an API failure.

Ready immediately
{
  "status": "Created",
  "checkout_role": "direct_payment",
  "pricing_status": "ready_for_payment",
  "requires_manual_quote": false,
  "payment_ready": true
}
Team review
{
  "status": "Awaiting Review",
  "checkout_role": "manual_review",
  "pricing_status": "awaiting_team_quote",
  "requires_manual_quote": true,
  "payment_ready": false
}
Shipping choice
{
  "checkout_role": "manual_review",
  "pricing_status": "shipping_selection_required",
  "payment_ready": false,
  "selected_shipping_option_id": null
}

If any item in a mixed cart needs manual review, the entire cart becomes one `Awaiting Review` order in v2. It is not split into child orders.

Collector Crypt carts are separate: one unique card, quantity `1`, never mixed with shipped products. After payment, `Paid` confirms SP3ND treasury receipt only—not provider purchase or wallet delivery. Approved Partners can search, quote, create, and pay card orders without a separate opt-in. SP3ND manually buys the exact card and transfers it to the buyer wallet.

checkout_role
Exactly `direct_payment` or `manual_review`; stored legacy roles are normalized.
pricing_status
Primary values are `awaiting_team_quote`, `shipping_selection_required`, and `ready_for_payment`; this field is informational.
payment_ready
The sole payment gate. No role, status, quote, or total authorizes payment by itself.

Create a server-priced cart

Send URLs or one Collector Crypt asset. SP3ND resolves product metadata and commerce values.

const response = await fetch(
  'https://us-central1-sp3nddotshop-prod.cloudfunctions.net/createPartnerCart',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': process.env.SP3ND_API_KEY,
      'X-API-Secret': process.env.SP3ND_API_SECRET
    },
    body: JSON.stringify({
      ship_to_country: 'United States',
      ship_to_postal_code: '10007',
      items: [{
        product_url: 'https://www.ebay.com/itm/123456789',
        quantity: 1
      }]
    })
  }
);

Physical carts expire after 30 minutes. A complete `shipping_address` can replace the country/postal shortcut. Legacy clients can send extra item metadata, but caller-supplied titles and prices are not treated as verified data.

Search and quote Collector Crypt cards

Discovery is live, authenticated, and read-only; the cart refetch is the pricing authority.

GET https://us-central1-sp3nddotshop-prod.cloudfunctions.net/searchCollectorCryptCards?q=charizard%20psa%2010&limit=20
X-API-Key: <api-key>
X-API-Secret: <api-secret>

// response
{
  "success": true,
  "schema_version": 2,
  "provider": "collectorcrypt",
  "currency": "USDC",
  "items": [{
    "pricing_source": "collectorcrypt_live_listing",
    "product_type": "tokenized_collectible",
    "fulfillment_type": "wallet_delivery",
    "card_id": "<provider-card-id>",
    "nft_address": "<asset-address>",
    "product_url": "https://collectorcrypt.com/assets/solana/<asset-address>",
    "back_image_url": "https://<provider-image-host>/back.jpg",
    "price": 125,
    "listing_price_usdc": 125,
    "currency": "USDC",
    "card_type": "Pokemon",
    "grading_id": "<provider-grading-id>",
    "insured_value_usd": 150,
    "listed_at": "2026-09-01T00:00:00.000Z",
    "listing_updated_at": "2026-09-01T00:01:00.000Z",
    "max_quantity": 1
  }],
  "next_cursor": null,
  "total": 1,
  "marketplace_total": 2400,
  "total_pages": 1,
  "category_counts": { "Pokemon": 1800, "Sports": 600 }
}
q
Optional, at most 200 characters: substring card/item-name search or exact NFT-address/grading-ID lookup. Omit to browse.
limit
Optional 1..100; defaults to 20.
cursor
Optional opaque next_cursor returned unchanged; nonblank, at most 2048 characters, no control characters; takes precedence over page.
page
Optional integer 1..10000 when no cursor is supplied.

Results include only native Solana Collector Crypt V2 buy-now listings priced in USDC with a supported `token_standard` (`Pnft`, `Cnft`, `StandardNft`, or `CoreNft`) and an exact cent-denominated price. `listing_price_usdc` mirrors generic `price`; insured value and listing timestamps are catalog metadata. Upstream totals, page totals, and category counts are computed before SP3ND filters ineligible rows, so they may exceed `items.length`. Search does not reserve the listing. Create a five-minute, one-card cart from the canonical asset URL or from `{ user_wallet: buyerWallet, items: [{ provider: "collectorcrypt", nft_address, quantity: 1 }] }`. Omit shipping and destination fields; the card cannot be mixed with Amazon or eBay items. An optional top-level cart `user_wallet` must be a valid on-curve Solana address. SP3ND stores it and uses it when the order request omits its own `user_wallet`; final buyer/recipient equality is enforced at order creation. An invalid cart wallet returns `USER_WALLET_INVALID`.

Marketplace storefronts

Published URL support and destination delivery are separate checks.

Amazon

amazon.com, amazon.co.uk, amazon.ca, amazon.de, amazon.fr, amazon.es, amazon.it, amazon.nl, amazon.com.be, amazon.pl, amazon.se, amazon.com.br, amazon.com.mx, amazon.com.au, amazon.in, amazon.co.jp, amazon.sg, amazon.ae, amazon.sa, amazon.eg, amazon.com.tr, amazon.co.za, amazon.ie, amazon.be, amazon.cn

Shares: a.co, amzn.to, amzn.eu, amzn.asia

eBay

ebay.com, ebay.ca, ebay.co.uk, ebay.de, ebay.at, ebay.fr, ebay.it, ebay.es, ebay.ie, ebay.nl, ebay.be, ebay.ch, ebay.pl, ebay.com.au, ebay.com.hk, ebay.com.my, ebay.ph, ebay.com.sg, ebay.in, ebay.cn, ebay.com.tw, ebay.vn, ebay.co.th

Product shares: ebay.io/m/<code>

Collector Crypt

Exact canonical URL: collectorcrypt.com/assets/solana/<asset-address>

Native Solana V2 buy-now listings in USDC only. The tokenized asset is delivered to `asset_recipient_wallet`; no physical shipping address is used.

Storefront support does not guarantee that a particular seller will ship a listing to every destination. SP3ND checks the listing using the final country and postal code. A cross-storefront order is valid only when SP3ND receives a verified ship-to-home quote for that address. Prefer the recipient country's storefront when one is available. Share links are expanded and revalidated server-side; SP3ND stores the canonical marketplace product URL.

`EBAY_UNDELIVERABLE` with `undeliverable_reason: "local_pickup_only"` is a hard listing restriction. `EBAY_QUOTE_UNAVAILABLE` is temporary or inconclusive and may be retried. Taiwan storefront URLs are recognized, but the listing still needs a verified quote to the buyer's exact Taiwan address.

Create an idempotent order

One stable idempotency key represents one checkout attempt.

const response = await fetch(
  'https://us-central1-sp3nddotshop-prod.cloudfunctions.net/createPartnerOrder',
  {
    method: 'POST',
    headers: {
      ...authHeaders,
      'Idempotency-Key': checkoutAttemptId
    },
    body: JSON.stringify({
      cart_id: cart.cart_id,
      customer_email: 'buyer@example.com',
      shipping_address: {
        name: 'Ada Buyer',
        recipient: 'Ada Buyer',
        address1: '123 Main Street',
        address2: 'Suite 4',
        city: 'New York',
        state: 'NY',
        postalCode: '10007',
        country: 'United States',
        phone: '+12125550123'
      }
    })
  }
);

Collector Crypt order

const response = await fetch(
  'https://us-central1-sp3nddotshop-prod.cloudfunctions.net/createPartnerOrder',
  {
    method: 'POST',
    headers: {
      ...authHeaders,
      'Idempotency-Key': cardCheckoutAttemptId
    },
    body: JSON.stringify({
      cart_id: cardCart.cart_id,
      customer_email: 'buyer@example.com',
      user_wallet: buyerWallet,
      asset_recipient_wallet: buyerWallet
    })
  }
);

Omit `shipping_address` for a Collector Crypt-only cart. Send the same valid, on-curve buyer address as `user_wallet` and `asset_recipient_wallet`. The server copies one to the other when a field is omitted, but new integrations should send both identically. Gifting is not supported; a mismatch returns `ASSET_RECIPIENT_WALLET_MISMATCH`. The wallet is frozen into the idempotent order and cannot change after payment preparation begins.

Idempotency-Key
Preferred header. `idempotency_key` in the body is supported for compatibility.
same key + same request
Returns the original order and can include `idempotent_replay: true`.
same key + changed request
Returns `409 IDEMPOTENCY_CONFLICT`.

Review quotes and shipping

Poll the order, present current choices, and submit an opaque option ID.

GET https://us-central1-sp3nddotshop-prod.cloudfunctions.net/getPartnerOrder?order_id=abc123

POST https://us-central1-sp3nddotshop-prod.cloudfunctions.net/selectPartnerOrderShippingOption
{
  "order_id": "abc123",
  "shipping_option_id": "standard"
}
quote_revision
Identifies the current team quote.
quote_expires_at
After expiry, fetch a new quote before continuing.
shipping_options
Each option uses shipping_option_id and carries label, shipping_amount, tax_amount, total_amount, and currency; description and estimated_delivery are optional.
selected_shipping_option_id
The canonical opaque identifier for the selected option, or null while a choice is required.
selected_shipping_option
The current reviewed choice, normalized to the same shape as an option.
selected_manual_shipping_option
Deprecated compatibility alias containing the same normalized object as selected_shipping_option.

Quote revision and expiry are enforced on selection. If the server returns a conflict, refresh the order and show the current options. Never calculate or patch the total client-side.

Pay a ready order

Shipped products default to createPartnerTransaction; Collector Crypt uses exact partnerPayment prepare/submit bytes.

Standard Partner API

If you were issued Partner API credentials for a normal server integration, use `createPartnerTransaction`. Do not use `payAgentOrder`. For shipped products, call the standard endpoint once, then build and submit the on-chain payment in your own wallet integration using only authoritative SP3ND values. Collector Crypt is the explicit exception below.

Never call `createPartnerTransaction` and then `payAgentOrder` for the same checkout. They are two different payment paths and must not share client-side settlement state.

Shipped-product Partner API flow

POST https://us-central1-sp3nddotshop-prod.cloudfunctions.net/createPartnerTransaction
Content-Type: application/json
X-API-Key: <api-key>
X-API-Secret: <api-secret>

{
  "order_id": "abc123",
  "sender_address": "<buyer-solana-wallet>"
}

// 201 response: use these exact server-derived fields
{
  "success": true,
  "status": "pending",
  "order_id": "abc123",
  "order_number": "ORD-...",
  "amount": 10.81,
  "currency": "USDC",
  "memo": "SP3ND Order: ORD-...",
  "recipient_address": "<sp3nd-treasury>"
}

`createPartnerTransaction` registers the authoritative payment attempt; it does not submit or sign a wallet transaction for you. Make that authenticated request on your server. Pass only its returned payment instructions to your trusted wallet signer. It rejects real Collector Crypt orders with `COLLECTOR_CRYPT_PAYMENT_METHOD_UNSUPPORTED`.

Exact Solana USDC construction

import {
  PublicKey,
  Transaction,
  TransactionInstruction,
} from '@solana/web3.js';
import {
  ASSOCIATED_TOKEN_PROGRAM_ID,
  TOKEN_PROGRAM_ID,
  createTransferCheckedInstruction,
  getAssociatedTokenAddressSync,
} from '@solana/spl-token';

const USDC_MINT = new PublicKey(
  'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
);
const MEMO_PROGRAM_ID = new PublicKey(
  'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'
);

// 10.81 USDC -> 10_810_000n. Never multiply a JS number by 1e6.
function toUsdcAtomicUnits(decimalAmount) {
  const match = /^(0|[1-9]\d*)(?:\.(\d{1,6}))?$/.exec(
    String(decimalAmount)
  );
  if (!match) throw new Error('Invalid USDC amount from SP3ND');
  const [, whole, fraction = ''] = match;
  return BigInt(whole) * 1_000_000n +
    BigInt(fraction.padEnd(6, '0'));
}

async function signAndBroadcastSp3ndPayment({
  payment,
  buyerPublicKey,
  connection,
  signTransaction,
}) {
  if (payment.status === 'confirmed') return null; // Never pay again.
  if (payment.status !== 'pending' || payment.currency !== 'USDC') {
    throw new Error('SP3ND payment is not payable');
  }

  const recipientOwner = new PublicKey(payment.recipient_address);
  const buyerUsdcAta = getAssociatedTokenAddressSync(
    USDC_MINT, buyerPublicKey, false,
    TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID
  );
  const recipientUsdcAta = getAssociatedTokenAddressSync(
    USDC_MINT, recipientOwner, false,
    TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID
  );
  const { blockhash, lastValidBlockHeight } =
    await connection.getLatestBlockhash('confirmed');

  const transaction = new Transaction({
    feePayer: buyerPublicKey,
    recentBlockhash: blockhash,
  }).add(
    createTransferCheckedInstruction(
      buyerUsdcAta,
      USDC_MINT,
      recipientUsdcAta,
      buyerPublicKey,
      toUsdcAtomicUnits(payment.amount),
      6,
      [],
      TOKEN_PROGRAM_ID
    ),
    new TransactionInstruction({
      programId: MEMO_PROGRAM_ID,
      keys: [],
      data: Buffer.from(payment.memo, 'utf8'),
    })
  );

  const signed = await signTransaction(transaction); // buyer signs
  const signature = await connection.sendRawTransaction(signed.serialize());
  await connection.confirmTransaction(
    { signature, blockhash, lastValidBlockHeight },
    'confirmed'
  );
  return signature;
}
  1. Use the returned amount, currency, memo, and recipient unchanged. Convert the decimal amount by padding to six places: `10.81` becomes exactly `10,810,000` atomic units, never a floating-point multiplication.
  2. Treat `recipient_address` as the treasury owner. Derive both canonical ATAs from the Solana mainnet USDC mint and the standard Token/Associated Token programs.
  3. Fetch a fresh blockhash and build a legacy `Transaction` with the buyer as fee payer and `TransferChecked` authority. Add `TransferChecked` followed by the Memo Program instruction using the exact memo bytes.
  4. Sign and broadcast through the partner's wallet and Solana RPC. Do not send `PAYMENT-SIGNATURE` or call a facilitator.
  5. Poll `getPartnerOrder` until SP3ND confirms `Paid`. Never send a second payment while confirmation is pending.

HTTP `200` with `status: confirmed` means the order was already paid and no transaction may be constructed. HTTP `201` with `status: pending` supplies the one payment above. On `409` or any other non-2xx response, do not broadcast; read the order and follow its lifecycle code.

Collector Crypt: exact prepare/submit flow

Card orders use `fulfillment_mode: manual` and `requires_manual_fulfillment: true`. Your approved Partner credentials support search, quotes, real orders, and payment without a separate opt-in. Confirmed USDC payment queues SP3ND's manual acquisition and wallet-delivery work; it does not automatically buy or transfer a card. Fulfillment records combine confirmed transaction references and operator attestations, plus current asset ownership for delivery. They do not cryptographically prove purchase or asset-transfer causality.
POST https://us-central1-sp3nddotshop-prod.cloudfunctions.net/partnerPayment
Content-Type: application/json
X-API-Key: <api-key>
X-API-Secret: <api-secret>

{
  "action": "prepare",
  "order_id": "abc123",
  "payer_address": "<buyer-solana-wallet>"
}

// 201 new preparation; a safe replay is 200 + idempotent_replay=true
{
  "success": true,
  "status": "payment_prepared",
  "idempotent_replay": false,
  "order_id": "abc123",
  "order_number": "ORD-...",
  "amount": 125,
  "currency": "USDC",
  "network": "solana-mainnet",
  "payer_address": "<buyer-solana-wallet>",
  "recipient_address": "<sp3nd-treasury>",
  "token_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "token_decimals": 6,
  "amount_atomic": "125000000",
  "memo": "SP3ND Order: ORD-...",
  "unsigned_transaction_base64": "<exact-unsigned-transaction>",
  "recent_blockhash": "<blockhash>",
  "last_valid_block_height": 123456789
}

Verify the displayed payment fields, then have exactly `payer_address` sign the exact returned transaction. Do not rebuild it, change instructions, replace the blockhash, or sign a second authorization. `PAYMENT_TRANSACTION_NEAR_EXPIRY` means do not sign; wait until the stated blockheight passes before preparing again.

POST https://us-central1-sp3nddotshop-prod.cloudfunctions.net/partnerPayment
Content-Type: application/json
X-API-Key: <api-key>
X-API-Secret: <api-secret>

{
  "action": "submit",
  "order_id": "abc123",
  "signed_transaction_base64": "<exact-wallet-signed-transaction>"
}

// 202 response
{
  "success": true,
  "status": "verifying_payment",
  "idempotent_replay": false,
  "order_id": "abc123",
  "order_number": "ORD-...",
  "transaction_signature": "<solana-signature>"
}

A prepare retry for the same unchanged order and payer safely returns the same valid bytes. A submit retry must reuse the exact same `signed_transaction_base64`. After a timeout, network error, or `PAYMENT_BROADCAST_UNKNOWN`, read the order first and never rebuild, re-sign, or prepare a replacement while the original outcome is unknown. `verifying_payment` is not `Paid`.

After SP3ND confirms treasury receipt, `Paid` still does not mean card delivery. The backend normally queues `pending_acquisition`; a claim mismatch reports `review_required`. Pending is not proof that SP3ND's manual operations team has acquired or transferred the card. A purchase signature is not final delivery. Authorized operations must atomically set the top-level order `status` to `Delivered` with that fulfillment evidence; clients use the top-level status as the completion gate and may show `asset_transfer_signature` when present. A sold or changed listing may require manual handling and a refund.
Advanced legacy agentic-skill appendix

Use `payAgentOrder` only if your client intentionally implements SP3ND's published legacy x402 agentic-skill contract. It is not the next step after `createPartnerTransaction`, and it is not the MCP payment path. Real Collector Crypt orders are rejected on this surface and use `partnerPayment` only. Follow the separate published SP3ND agentic skill or contact SP3ND for the current legacy integration contract.

MCP boundary: the public SP3ND MCP tools use the same `partnerPayment` prepare/submit backend as the Collector Crypt Partner API path, but bind it to their own OAuth session and approval ticket. MCP clients stay inside those tools; direct Partner API clients use their server credentials.

For these paths, `order_number` is optional and validated when sent. Caller-provided `amount`, `currency`, `memo`, and `recipient_address` are ignored. Payment can begin only when the latest response has `payment_ready: true`; `pricing_status` is informational and is never a second payment gate.

`ORDER_NOT_PAYMENT_READY` means keep the customer in review and poll the order. `PAYMENT_SETTLEMENT_IN_PROGRESS` also means poll without resubmitting payment. If `PAYMENT_SETTLEMENT_UNKNOWN` is returned, do not retry: retain the order ID and request manual reconciliation.

Supported endpoints

Cloud Function endpoint names are part of the public contract.

GETsearchCollectorCryptCards?q=...&limit=...&cursor=...&page=...Search live Collector Crypt USDC cards
POSTcreatePartnerCartCreate a server-priced cart
POSTaddItemToPartnerCart/{cartId}Add one item
PATCHupdateCartItemQuantity/{cartId}/{itemId}Change quantity
DELETEremoveCartItem/{cartId}/{itemId}Remove an item
PATCHupdateCartShippingAddress/{cartId}Change destination and reprice
GETgetPartnerCart/{cartId}Read a cart
POSTcreatePartnerOrderCreate an order
GETgetPartnerOrder?order_id=...Read one order
GETgetPartnerOrdersList orders
GETgetPartnerKpis?start_date=...&end_date=...Read aggregate-only KPIs
POSTselectPartnerOrderShippingOptionChoose reviewed shipping
POSTcreatePartnerTransactionShipped-product payment attempt; rejects Collector Crypt
POSTpartnerPaymentPrepare or submit exact Collector Crypt payment bytes
POSTpayAgentOrderAdvanced legacy agentic-skill clients only

To list all orders, omit `status` or use `status=all`. The plural order endpoint accepts integer `limit` (`1..100`, default `50`) and `offset` (`0..499`, default `0`), with `limit + offset <= 500`. Optional `user_wallet` and `customer_email` filters are applied before pagination. The plural `addItemsToPartnerCart` endpoint is not supported in v2.

Aggregate reporting

Read current partner KPIs without receiving or storing customer order rows.

GET https://us-central1-sp3nddotshop-prod.cloudfunctions.net/getPartnerKpis?start_date=2026-08-01T00:00:00.000Z&end_date=2026-09-01T00:00:00.000Z

X-API-Key: <api-key>
X-API-Secret: <api-secret>

`start_date` is inclusive and `end_date` is exclusive. Supply both as ISO-8601 timestamps with explicit timezones. Omit both for the trailing 30 days; the maximum range is 90 days. A request may scan at most 5,000 orders. A larger scan fails with HTTP `413` and `KPI_SCAN_LIMIT_EXCEEDED`; partial results are never returned.

The response separates `gross_created` from `settled` volume. `gross_created` includes every non-test order created in the range, including later cancelled or refunded orders. Fees and revshare are counted only in `settled`. Current `cancelled` and `refunded` buckets report count and gross order value, not actual loss or refund amounts. The status breakdown remains available. No order IDs, items, wallets, emails, addresses, or payment identifiers are returned.

Lifecycle conflicts

Use machine-readable codes and refresh state after quote conflicts.

ORDER_NOT_PAYMENT_READY

Poll the order; do not submit payment.

ORDER_NOT_PAYABLE

Stop; this order cannot accept payment.

PAYMENT_SETTLEMENT_IN_PROGRESS

Do not resubmit payment; poll the order.

PAYMENT_SETTLEMENT_UNKNOWN

Do not retry; retain the order ID for manual reconciliation.

IDEMPOTENCY_CONFLICT

Use the original payload or a new checkout key.

COLLECTOR_CRYPT_SINGLE_ITEM_REQUIRED

Create a one-card cart and do not mix it with shipped products.

COLLECTOR_CRYPT_QUERY_INVALID / COLLECTOR_CRYPT_LIMIT_INVALID / COLLECTOR_CRYPT_CURSOR_INVALID / COLLECTOR_CRYPT_PAGE_INVALID

Fix the discovery input; pass an upstream cursor back unchanged.

USER_WALLET_INVALID

Use a valid on-curve Solana address for the optional cart user_wallet.

COLLECTOR_CRYPT_LISTING_CHANGED

Create a fresh cart from the current live listing.

COLLECTOR_CRYPT_LISTING_UNAVAILABLE

Stop checkout; the card is no longer an eligible listing.

COLLECTOR_CRYPT_LISTING_IDENTITY_INVALID

Stop; the listing lacks an immutable asset/receipt identity.

COLLECTOR_CRYPT_LISTING_RESERVED

Stop; another SP3ND order owns this exact listing receipt.

COLLECTOR_CRYPT_ORDER_CHANGED / COLLECTOR_CRYPT_RESERVATION_EXPIRED

Do not pay; read or rebuild the card order as directed.

COLLECTOR_CRYPT_PAYMENT_METHOD_UNSUPPORTED

Use partnerPayment; both legacy payment endpoints reject real cards.

ASSET_RECIPIENT_WALLET_MISMATCH

Use the same wallet for user_wallet and asset_recipient_wallet; gifting is unavailable.

PAYER_ADDRESS_INVALID / PAYER_ADDRESS_MISMATCH

Prepare with the valid buyer wallet frozen on the order.

ORDER_ID_REQUIRED / ASSET_RECIPIENT_WALLET_REQUIRED

Send the opaque order ID and the same valid on-curve buyer/delivery wallet.

SIGNED_TRANSACTION_INVALID / SIGNED_TRANSACTION_REJECTED

Submit only the bounded exact signed serialization returned by prepare.

PAYMENT_NOT_PREPARED / PAYMENT_ATTEMPT_EXISTS / PAYMENT_ATTEMPT_INVALID

Read the current order and attempt; never create a parallel payment.

ORDER_CHANGED / PAYMENT_TOTAL_INVALID / PAYMENT_AMOUNT_INVALID

Stop and read the authoritative order; do not construct replacement payment values.

PAYMENT_SIGNATURE_CONFLICT / PAYMENT_SIGNATURE_REUSED

Stop; never attach another signature or reuse one across orders.

COLLECTOR_CRYPT_PRICING_CONFIGURATION_INVALID

Stop; SP3ND cannot create a card order whose total is below provider cost.

TEST_PAYMENT_UNSUPPORTED

Do not send a real wallet payment for a test order.

PAYMENT_TRANSACTION_NEAR_EXPIRY

Do not sign; wait past the last-valid blockheight before preparing again.

PAYMENT_TRANSACTION_FAILED / PAYMENT_TRANSACTION_EXPIRED

The old attempt was proved terminal and released; prepare fresh bytes.

PAYMENT_STATUS_UNAVAILABLE / PAYMENT_PREFLIGHT_UNAVAILABLE

Preserve and retry only the exact signed bytes when retryable.

PAYMENT_RECONCILIATION_PENDING

Keep the payment locked and retry only the original signed bytes.

QUOTE_EXPIRED

Fetch the current order and quote.

QUOTE_REVISION_MISMATCH

Refresh before selecting shipping.

CART_EXPIRED

Create and price a new cart.

EBAY_UNDELIVERABLE

Stop for this listing and destination. A local-pickup-only listing is not retryable.

EBAY_QUOTE_UNAVAILABLE

The quote was temporary or inconclusive; retry later.

RATE_LIMITED

Back off before retrying.

Migration checklist

Persist order_id, not only order_number.
Gate payment on payment_ready.
Treat Awaiting Review as resumable.
Poll getPartnerOrder with backoff.
Submit shipping option IDs unchanged.
Let SP3ND derive every payment field.
Use one idempotency key per checkout.
Handle mixed carts as one review order.
Keep Collector Crypt carts to one card.
Freeze asset_recipient_wallet before payment.
Treat Paid as treasury receipt, not card delivery.

Support

Email support@sp3nd.shop with your partner name, endpoint, timestamp, and `order_id` or `cart_id`. Never send an API secret or signed payment payload.