API referencePurchase status & history

Purchases

Fetch and list merchant purchases. All require Authorization: Bearer mer_live_… (Authentication).

To create a purchase, see Buy.

Fetch a purchase

GET /api/v1/merchant/purchases/{purchaseId}
curl --compressed "https://merchant-api.tradeon.market/api/v1/merchant/purchases/1a2b3c4d-5e6f-7080-91a2-b3c4d5e6f708" \
  -H "Authorization: Bearer mer_live_…"

200 OK:

{
  "purchase_id": "1a2b3c4d-5e6f-7080-91a2-b3c4d5e6f708",
  "custom_id": "order-2026-05-05-0001",
  "status": "completed",
  "item": {
    "id": "8e42bb9c-2e11-4d40-9d51-6e5d2d4b2cf1",
    "market_hash_name": "AK-47 | Redline (Field-Tested)",
    "image_url": "https://cdn.tradeon.market/items/ak47-redline-ft.png",
    "exterior": "Field-Tested",
    "float": 0.2451,
    "delivery_type": "instant",
    "estimated_delivery_minutes": 2
  },
  "price": 18.40,
  "target_steam_id": "76561197960278073",
  "trade_offer_id": "9876543210",
  "trade_offer_url": "https://steamcommunity.com/tradeoffer/9876543210",
  "created_at": "2026-05-05T16:00:00.000Z",
  "completed_at": "2026-05-05T16:02:13.421Z",
  "failure": null
}

price is the top-level purchase price; item has no price field. Nullable detail fields include item.id (for a removed catalog row), image, exterior, float, estimated delivery time, recipient, trade-offer fields and completion time. Steam IDs remain strings.

When the purchase has failed, failure is non-null. This is a response fragment:

{
  "failure": {
    "code": "PROVIDER_ERROR",
    "message": "Provider could not deliver the item",
    "refunded_amount": 18.40
  }
}

Errors

HTTPcodeWhen
400MERCHANT_INVALID_STATUS?status= is not one of created, processing, sent_to_steam, completed, failed (GET /purchases only).
404MERCHANT_PURCHASE_NOT_FOUNDPurchase does not exist or belongs to another merchant.

List purchases

GET /api/v1/merchant/purchases

Cursor-paginated, newest first. A custom_id lookup can return multiple attempts from buy-by-name. Keep their individual purchase IDs and follow pagination; do not assume the first observed attempt is the final outcome of a still-running by-name call.

Query parameters

NameTypeNotes
cursorstringOpaque, from previous next_cursor.
limitint1–200, default 50.
statusstringFilter — one of created, processing, sent_to_steam, completed, failed. See status values. Unknown values return 400 MERCHANT_INVALID_STATUS.
custom_idstringExact match.
target_steam_idstringExact match.
from / toISO 8601created_at window.

Example

curl --compressed "https://merchant-api.tradeon.market/api/v1/merchant/purchases?status=completed&limit=2" \
  -H "Authorization: Bearer mer_live_…"

Each entry in purchases has the full response shape shown above. For an empty result:

{
  "purchases": [],
  "next_cursor": null
}

Status values

completed ends delivery and failed ends that attempt; the rest are in flight. A later Steam Trade Protection rollback can still change a completed purchase to failed. Continue handling reversal events after delivery.

StatusEnds delivery/attemptMeaning
createdAccepted, balance debited, awaiting worker pickup.
processingAcquiring the item from upstream (incl. provider-top-up retries).
sent_to_steamTrade offer dispatched on Steam, waiting for buyer to accept.
completed✓Buyer accepted and the item was delivered; a later protection rollback remains possible.
failed✓Buyer-declined / cancelled / refunded. Inspect failure.code and failure.refunded_amount.

failed does not itself confirm a refund. Inspect failure.refunded_amount, refund events and the balance; a refund amount can be absent when no refund has been confirmed. Prefer webhooks over polling and use this endpoint for reconciliation: Event Catalogue.

Failure and offer metadata

See the complete purchase failure code reference. GET and list return the same failure.code and message. refunded_amount: 0 marks a buyer-fault outcome with no refund; null means no refund is reported.

trade_offer_id and trade_offer_url can remain present after failure or rollback. Null means the provider has not supplied the ID, even if an offer may have been sent.

When buy-sync observes a created purchase fail, or buy-by-name replays a failed attempt, the 409 body keeps error and additionally returns purchase_id, custom_id, failure, trade_offer_id, and trade_offer_url. Pre-creation errors and by-name exhaustion without a selected final response keep the ordinary HTTP error body.