Discover/ShopGoodwill API
live

ShopGoodwill APIshopgoodwill.com

Access ShopGoodwill auction listings, item details, bid history, shipping info, categories, and featured items via a structured JSON API.

Endpoints
9
Updated
2mo ago

What is the ShopGoodwill API?

The ShopGoodwill API covers 9 endpoints for querying Goodwill's online auction marketplace, returning structured data on listings, pricing, bids, and shipping. The get_item_details endpoint alone surfaces over 8 fields per item including current bid price, number of bids, HTML description, and handling fees. Use search_listings to filter by keyword, price range, category, or seller, and paginate results with full category tree metadata alongside each response.

Try it
Page number (1-based).
Search keyword.
Minimum price filter.
Results per page.
Seller ID to filter by.
Maximum price filter.
Category ID to filter by. 0 returns all categories.
Sort column: 1 for ending soonest, 2 for newest listed.
Include closed auctions. Accepted values: true, false.
Sort descending. Accepted values: true, false.
api.parse.bot/scraper/49f1b060-de69-477f-9028-da1eea2aff21/<endpoint>
Ready to send
Fill in the parameters and hit sign in to send to see live response data here.
Call it over HTTPgrab a free API key at signup
curl -X GET 'https://api.parse.bot/scraper/49f1b060-de69-477f-9028-da1eea2aff21/search_listings?page=1&query=shoes&page_size=5' \
  -H 'X-API-Key: $PARSE_API_KEY'
Python SDK · recommended

Typed, relational, agent-ready

A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.

  • Fully typed · autocompletes
  • Objects link to objects
  • Typed errors & pagination

Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:

uv add parse-sdk
uv run parse init
uv run parse add --marketplace shopgoodwill-com-api

uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.

"""
ShopGoodwill API Client
Search and browse auction listings on shopgoodwill.com.
Get your API key from: https://parse.bot/settings
"""

import os
import requests
from typing import Any, Dict, List, Optional


class ParseClient:
    """Client for interacting with the ShopGoodwill Parse API."""

    def __init__(self, api_key: Optional[str] = None):
        """
        Initialize the Parse API client.

        Args:
            api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
        """
        self.base_url = "https://api.parse.bot"
        self.scraper_id = "49f1b060-de69-477f-9028-da1eea2aff21"
        self.api_key = api_key or os.getenv("PARSE_API_KEY")

        if not self.api_key:
            raise ValueError("API key must be provided or set in PARSE_API_KEY environment variable")

    def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
        """
        Make a request to the Parse API.

        Args:
            endpoint: The endpoint name (e.g., 'search_listings')
            method: HTTP method ('GET' or 'POST')
            **params: Query/body parameters for the endpoint

        Returns:
            JSON response from the API

        Raises:
            requests.RequestException: If the request fails
        """
        url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }

        if method.upper() == "GET":
            response = requests.get(url, headers=headers, params=params)
        elif method.upper() == "POST":
            response = requests.post(url, headers=headers, json=params)
        else:
            raise ValueError(f"Unsupported HTTP method: {method}")

        response.raise_for_status()
        return response.json()

    def search_listings(
        self,
        query: Optional[str] = None,
        category_id: Optional[int] = None,
        low_price: str = "0",
        high_price: str = "999999",
        page: int = 1,
        page_size: int = 40,
        sort_column: str = "1",
        sort_descending: str = "false",
        seller_id: Optional[str] = None,
        closed_auctions: str = "false"
    ) -> Dict[str, Any]:
        """
        Search for items on shopgoodwill.com with filters.

        Args:
            query: Search keyword
            category_id: Category ID to filter by
            low_price: Minimum price
            high_price: Maximum price
            page: Page number (1-based)
            page_size: Number of items per page
            sort_column: Column to sort by (1=Ending Soonest, 2=Newly Listed)
            sort_descending: Whether to sort descending
            seller_id: Seller ID to filter by
            closed_auctions: Whether to search for closed auctions

        Returns:
            Search results with items and item count
        """
        return self._call(
            "search_listings",
            method="GET",
            query=query,
            category_id=category_id,
            low_price=low_price,
            high_price=high_price,
            page=page,
            page_size=page_size,
            sort_column=sort_column,
            sort_descending=sort_descending,
            seller_id=seller_id,
            closed_auctions=closed_auctions
        )

    def get_item_details(self, item_id: str) -> Dict[str, Any]:
        """
        Get full details for a single item by its ID.

        Args:
            item_id: The item ID

        Returns:
            Item details including title, description, price, and bid count
        """
        return self._call("get_item_details", method="GET", item_id=item_id)

    def get_categories(self) -> List[Dict[str, Any]]:
        """
        Get all top-level categories.

        Returns:
            List of category objects with categoryId, name, and children
        """
        return self._call("get_categories", method="GET")

    def get_subcategories(self, parent_category_id: str) -> List[Dict[str, Any]]:
        """
        Get subcategories for a given parent category ID.

        Args:
            parent_category_id: The parent category ID

        Returns:
            List of subcategory objects
        """
        return self._call("get_subcategories", method="GET", parent_category_id=parent_category_id)

    def get_item_shipping(self, item_id: str) -> Dict[str, Any]:
        """
        Get shipping information for an item.

        Args:
            item_id: The item ID

        Returns:
            Shipping and handling price information
        """
        return self._call("get_item_shipping", method="GET", item_id=item_id)

    def get_item_bid_history(self, item_id: str) -> Dict[str, Any]:
        """
        Get the bid history for an item.

        Args:
            item_id: The item ID

        Returns:
            Bid history and summary information
        """
        return self._call("get_item_bid_history", method="GET", item_id=item_id)

    def get_advanced_search_filters(self) -> Dict[str, Any]:
        """
        Get all available search filters (categories and sellers).

        Returns:
            Dictionary with categories and sellers arrays
        """
        return self._call("get_advanced_search_filters", method="GET")

    def get_featured_items(self) -> Dict[str, Any]:
        """
        Get featured items from the homepage gallery.

        Returns:
            Featured items data with items array and total count
        """
        return self._call("get_featured_items", method="GET")

    def get_newly_listed(
        self,
        category_id: int = 0,
        page: int = 1,
        page_size: int = 40
    ) -> Dict[str, Any]:
        """
        Get the most recently listed auction items.

        Args:
            category_id: Category ID to filter by (0 for all)
            page: Page number (1-based)
            page_size: Number of items per page

        Returns:
            Recently listed search results
        """
        return self._call(
            "get_newly_listed",
            method="GET",
            category_id=category_id,
            page=page,
            page_size=page_size
        )


if __name__ == "__main__":
    # Initialize client
    client = ParseClient()

    print("=" * 80)
    print("ShopGoodwill Auction Deal Finder - Practical Workflow")
    print("=" * 80)

    # Step 1: Search for items matching criteria (vintage items under $100)
    print("\n[STEP 1] Searching for vintage items priced under $100...")
    search_results = client.search_listings(
        query="vintage",
        low_price="0",
        high_price="100",
        page=1,
        page_size=8,
        sort_column="1"  # Sort by ending soonest
    )

    items = search_results.get("searchResults", {}).get("items", [])
    total_count = search_results.get("searchResults", {}).get("itemCount", 0)
    print(f"   ✓ Found {total_count} total vintage items (showing {len(items)} on first page)")

    if not items:
        print("   No items found. Fetching featured items instead...")
        featured_response = client.get_featured_items()
        items = featured_response.get("items", [])[:8]
        print(f"   ✓ Using {len(items)} featured items for analysis")

    # Step 2: Analyze each item's total cost and bid activity
    print("\n[STEP 2] Analyzing item details, shipping, and bid activity...")
    items_analysis = []

    for idx, item in enumerate(items, 1):
        item_id = str(item.get("itemId"))
        title = item.get("title", "Unknown")[:60]  # Truncate for readability
        current_price = float(item.get("currentPrice", 0))
        num_bids = item.get("numBids", 0)

        # Get detailed item information
        try:
            item_details = client.get_item_details(item_id)
            description_length = len(item_details.get("description", ""))
        except Exception as e:
            print(f"   Warning: Could not fetch details for item {item_id}: {e}")
            description_length = 0

        # Get shipping information
        try:
            shipping_info = client.get_item_shipping(item_id)
            shipping_price = float(shipping_info.get("shippingPrice", 0))
            handling_price = float(shipping_info.get("handlingPrice", 0))
            shipper = shipping_info.get("shipper", "Unknown")
        except Exception as e:
            print(f"   Warning: Could not fetch shipping for item {item_id}: {e}")
            shipping_price = 0
            handling_price = 0
            shipper = "Unknown"

        # Get bid history for activity metrics
        try:
            bid_history = client.get_item_bid_history(item_id)
            bid_summary = bid_history.get("bidSummary", [])
            highest_bidder = bid_summary[-1].get("bidderName", "N/A") if bid_summary else "No bids"
        except Exception as e:
            print(f"   Warning: Could not fetch bid history for item {item_id}: {e}")
            highest_bidder = "N/A"

        total_cost = current_price + shipping_price + handling_price

        item_analysis = {
            "item_id": item_id,
            "title": title,
            "current_price": current_price,
            "shipping_price": shipping_price,
            "handling_price": handling_price,
            "total_cost": total_cost,
            "num_bids": num_bids,
            "shipper": shipper,
            "highest_bidder": highest_bidder,
            "description_length": description_length
        }
        items_analysis.append(item_analysis)

        print(f"\n   Item {idx}: {title}")
        print(f"      Current Bid: ${current_price:.2f}")
        print(f"      Shipping: ${shipping_price:.2f} via {shipper}")
        print(f"      Handling: ${handling_price:.2f}")
        print(f"      Total Cost: ${total_cost:.2f}")
        print(f"      Bid Count: {num_bids} | Top Bidder: {highest_bidder}")

    # Step 3: Find the best deals (lowest total cost)
    print("\n[STEP 3] TOP DEALS - Lowest total cost items")
    print("   " + "-" * 70)
    sorted_by_cost = sorted(items_analysis, key=lambda x: x["total_cost"])
    for rank, item in enumerate(sorted_by_cost[:3], 1):
        print(f"   {rank}. {item['title']}")
        print(f"      Total Cost: ${item['total_cost']:.2f} "
              f"(Bid: ${item['current_price']:.2f} + Ship: ${item['shipping_price']:.2f})")

    # Step 4: Find most competitive items (high bid activity)
    print("\n[STEP 4] HOTTEST ITEMS - Most bids/highest competition")
    print("   " + "-" * 70)
    sorted_by_bids = sorted(items_analysis, key=lambda x: x["num_bids"], reverse=True)
    for rank, item in enumerate(sorted_by_bids[:3], 1):
        print(f"   {rank}. {item['title']}")
        print(f"      Bids: {item['num_bids']} | Current Price: ${item['current_price']:.2f}")

    # Step 5: Best value items (low total cost AND good descriptions)
    print("\n[STEP 5] BEST VALUE - Low cost with detailed descriptions")
    print("   " + "-" * 70)
    # Filter items with meaningful descriptions
    detailed_items = [item for item in items_analysis if item["description_length"] > 100]
    if detailed_items:
        sorted_by_value = sorted(detailed_items, key=lambda x: x["total_cost"])
        for rank, item in enumerate(sorted_by_value[:3], 1):
            print(f"   {rank}. {item['title']}")
            print(f"      Total Cost: ${item['total_cost']:.2f} "
                  f"| Description: {item['description_length']} characters")
    else:
        print("   (No items with detailed descriptions found)")

    # Step 6: Browse categories for future searches
    print("\n[STEP 6] Available categories for targeted searches")
    print("   " + "-" * 70)
    try:
        categories = client.get_categories()
        if isinstance(categories, dict):
            categories = categories.get("data", [])
        if isinstance(categories, list):
            print(f"   Total categories: {len(categories)}")
            for cat in categories[:5]:
                cat_name = cat.get("name", "Unknown")
                cat_id = cat.get("categoryId", "N/A")
                num_children = len(cat.get("children", []))
                print(f"   - {cat_name} (ID: {cat_id}) - {num_children} subcategories")
    except Exception as e:
        print(f"   Could not fetch categories: {e}")

    # Summary statistics
    print("\n[SUMMARY] Analysis Results")
    print("   " + "-" * 70)
    avg_cost = sum(item["total_cost"] for item in items_analysis) / len(items_analysis)
    avg_bids = sum(item["num_bids"] for item in items_analysis) / len(items_analysis)
    lowest_cost = min(items_analysis, key=lambda x: x["total_cost"])["total_cost"]
    highest_bids = max(items_analysis, key=lambda x: x["num_bids"])["num_bids"]

    print(f"   Items Analyzed: {len(items_analysis)}")
    print(f"   Average Total Cost: ${avg_cost:.2f}")
    print(f"   Lowest Total Cost: ${lowest_cost:.2f}")
    print(f"   Average Bids per Item: {avg_bids:.1f}")
    print(f"   Highest Bid Count: {highest_bids}")

    print("\n" + "=" * 80)
    print("✓ Deal analysis complete! Review the recommendations above.")
    print("=" * 80)
All endpoints · 9 totalmissing one? ·

Search for items on shopgoodwill.com with filters. Returns paginated auction listings with category metadata.

Input
ParamTypeDescription
pageintegerPage number (1-based).
querystringSearch keyword.
low_pricestringMinimum price filter.
page_sizeintegerResults per page.
seller_idstringSeller ID to filter by.
high_pricestringMaximum price filter.
category_idintegerCategory ID to filter by. 0 returns all categories.
sort_columnstringSort column: 1 for ending soonest, 2 for newest listed.
closed_auctionsstringInclude closed auctions. Accepted values: true, false.
sort_descendingstringSort descending. Accepted values: true, false.
Response
{
  "type": "object",
  "fields": {
    "searchResults": "object containing items array and itemCount integer",
    "categoryListModel": "object containing categoryModel array of category tree nodes"
  },
  "sample": {
    "data": {
      "searchResults": {
        "items": [
          {
            "title": "UGG Fluff Yeah Women's Cream Slide Slippers Sz 8 Shoes",
            "itemId": 263858212,
            "endTime": "2026-05-14T09:35:16",
            "numBids": 6,
            "sellerId": 337,
            "categoryId": 1703,
            "categoryName": "Size 8",
            "currentPrice": 25,
            "shippingPrice": 0
          }
        ],
        "itemCount": 19236
      },
      "categoryListModel": {
        "categoryModel": [
          {
            "name": "Antiques",
            "children": [],
            "categoryId": 1,
            "levelNumber": 1
          }
        ]
      }
    },
    "status": "success"
  }
}

About the ShopGoodwill API

Searching and Browsing Listings

The search_listings endpoint accepts filters for query, low_price, high_price, category_id, seller_id, and sort_column. Sort options cover ending-soonest (1) and newest-listed (2). Each response includes a searchResults object with an items array and a total itemCount, plus a categoryListModel containing a full category tree. The get_newly_listed endpoint mirrors this response shape but is pre-sorted by recency and accepts page, page_size, and category_id without requiring a keyword.

Item Details, Bids, and Shipping

get_item_details returns the full auction record for a single item: title, currentPrice, numberOfBids, bidHistory (split into bidSummary and bidComplete arrays), an HTML description, and both shippingPrice and handlingPrice. The standalone get_item_bid_history endpoint returns the same bid arrays plus an auctionClosed boolean and itemCurrentPrice, useful for polling auctions near close. get_item_shipping returns the carrier name (shipper), weight, handlingPrice, noCombineShipping, and an allowShippingCalculation flag indicating whether dynamic shipping rates can be computed for the item.

Categories and Discovery

get_categories returns the full top-level category list with nested children arrays and integer categoryId values ready to pass directly into search_listings or get_newly_listed. get_subcategories accepts a parent_category_id and returns only the children of that node. get_advanced_search_filters returns both the full category tree and a sellers array of seller/location objects with sellerId and searchFilterName fields — useful for populating filter UIs. get_featured_items returns the homepage gallery as an items array with a total count.

Reliability & maintenance

The ShopGoodwill API is a managed, monitored endpoint for shopgoodwill.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when shopgoodwill.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.

This isn't an official shopgoodwill.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.

Will this API break when the source site changes?+
It's built not to. Every endpoint is health-checked on a schedule with automated test probes. When the source site changes and a check fails, the API is automatically queued for repair and re-verified — that's the self-healing layer. Each API page shows when its endpoints were last verified. And because marketplace APIs are shared, any fix reaches everyone using it.
Is this an official API from the source site?+
No — Parse APIs are independent, managed REST wrappers over publicly available data. That is the point: where a site has no official API (or only a limited one), Parse gives you a maintained, monitored endpoint for that data and keeps it working as the site changes — so you get a stable contract over a source that never promised one.
Can I fix or extend this API myself if I need a new endpoint or field?+
Yes — and you don't have to wait on us. This API was generated by the Parse agent, which stays attached. Describe the change in plain English ("add an endpoint that returns reviews", "fix the price field") in the revise box on the API page or via the revise_api MCP tool, and the agent rebuilds it against the live site in minutes. Contributing the change back to the public API is free.
What happens if I call an endpoint that has an issue?+
Errors are machine-readable: a bad call returns a clean status with the list of available endpoints and a repair hint, so an agent (or you) can recover or trigger a fix instead of failing silently. Confirmed failures feed the automatic repair queue.
Common use cases
  • Track auction price history on specific item categories using get_item_bid_history and auctionClosed signals
  • Build a price-alert tool that polls search_listings with low_price/high_price filters for undervalued items
  • Aggregate newly listed electronics or collectibles by combining get_newly_listed with a specific category_id
  • Display accurate shipping cost breakdowns using shippingPrice, handlingPrice, and noCombineShipping from get_item_shipping
  • Populate a faceted search UI with seller and category filter options from get_advanced_search_filters
  • Monitor a specific seller's inventory over time by filtering search_listings with a fixed seller_id
  • Surface homepage trending inventory programmatically via get_featured_items for a deal-aggregation feed
Pricing & limitsSee full pricing →
TierPriceCredits/monthRate limit
Free$0/mo1005 req/min
Hobby$30/mo1,00020 req/min
Developer$100/mo5,000100 req/min

One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.

Frequently asked questions
Does ShopGoodwill have an official developer API?+
ShopGoodwill does not publish an official public developer API or documentation for third-party access to its auction data.
What bid data does `get_item_bid_history` return, and how is it structured?+
get_item_bid_history returns two arrays: bidSummary (each entry includes bidderName and amount) and bidComplete (each entry includes bidAmount and bidTime). It also returns an auctionClosed boolean and the itemCurrentPrice at the time of the request. It does not return bidder profile details beyond the display name.
Can I place bids or create watchlists through this API?+
The API covers read-only data: search, item details, bid history, shipping, and categories. Placing bids, managing watchlists, or accessing account data are not currently exposed. You can fork this API on Parse and revise it to add those endpoints.
How does pagination work in `search_listings`?+
search_listings accepts a 1-based page integer and a page_size integer. The response includes itemCount in the searchResults object, which you can use to calculate total pages. If page_size is omitted, a default page size applies. There is no cursor-based pagination; only offset-style page numbers are supported.
Does the API return sold or completed auction data?+
The API returns live and recently listed auction data. Historical sold-item archives and final hammer prices for closed auctions are not currently covered beyond the auctionClosed flag and current price available in get_item_bid_history. You can fork this API on Parse and revise it to add a completed-auctions endpoint if that data becomes accessible.
Page content last updated . Spec covers 9 endpoints from shopgoodwill.com.
Related APIs in MarketplaceSee all →
shpock.com API
Search and browse products listed on Shpock.com, view detailed listing information and seller profiles, and explore all available marketplace categories. Find what you're looking for by searching inventory, checking seller histories, and discovering related items from individual merchants.
ebay.com API
Search and monitor eBay listings across any category, with support for active and completed/sold listings. Retrieve item details, pricing history, seller profiles and feedback, and category data. Filter by keyword, category, condition, seller, and sort order to support price research, market analysis, and inventory monitoring.
bidorbuy.co.za API
Search and browse products on Bob Shop, view detailed product information, seller profiles and ratings, explore category listings, and discover current promotions. Get search suggestions and navigate the complete product catalog to find exactly what you're looking for.
grailed.com API
Access Grailed's fashion resale marketplace: search listings by designer, category, size, and condition; retrieve listing details, seller profiles and reviews; and browse categories, popular designers, and curated collections.
lista.mercadolivre.com.br API
Search and browse products from Mercado Livre Brazil, view detailed pricing and offers, and explore categories to find daily deals and product information. Get comprehensive product details including specifications and current market offers all in one place.
auctionzip.com API
Search and browse auction lots across the AuctionZip marketplace, view detailed lot information and complete auction catalogs, track historical prices realized, and discover auctioneers by name or location. Access auction schedules, item specifications, seller terms, and top-performing auctioneers.
auctions.godaddy.com API
Search and browse domain auction listings on GoDaddy Auctions, including expired domains and closeout (Buy It Now) listings. Retrieve current bid prices, bid counts, auction end times, domain valuations, and backlink metrics across all active auction types.
ebay.ca API
Search and compare eBay Canada listings with detailed item information, pricing history from completed sales, and seller profiles to make informed buying decisions. Discover current deals, browse product categories, and view seller feedback and ratings all in one place.