Curtfire APIcurtfire.co.za ↗
Access Curtfire South African marketplace data: keyword search, category tree, product listings, and full product details including variants and ZAR pricing.
What is the Curtfire API?
The Curtfire API exposes 4 endpoints covering the full curtfire.co.za South African online marketplace catalogue. Use search_products to run keyword searches with sorting and pagination, retrieve the complete category tree via list_categories, browse products by category through list_category_products, and pull full product detail records — including variant option groups, ZAR pricing, stock status, and gallery images — with get_product.
curl -X GET 'https://api.parse.bot/scraper/015c1303-2759-44f7-bbbe-4696149ae357/search_products?keyword=watch' \ -H 'X-API-Key: $PARSE_API_KEY'
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 curtfire-co-za-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.
"""Walkthrough: Curtfire marketplace SDK — browse categories, search products, drill into details."""
from parse_apis.curtfire_co_za_api import Curtfire, ProductSort, ProductNotFound
client = Curtfire()
# Browse the category tree and pick the first top-level category.
top_category = None
for cat in client.categories.list(limit=10):
if cat.parent_category_id == 0:
top_category = cat
break
# List products in that category, sorted by price ascending.
if top_category is not None:
print(f"Category: {top_category.name}")
for item in top_category.products.list(sort=ProductSort.PRICE_ASC, limit=3):
print(f" {item.name} — R{item.price:.2f}, in stock: {item.in_stock}")
# Keyword search across the whole catalogue.
hit = client.product_summaries.search(keyword="watch", limit=1).first()
# Navigate from the summary card to the full product detail.
if hit is not None:
detail = hit.details()
print(f"\n{detail.name} (R{detail.price:.2f} {detail.currency})")
print(f" Stock: {detail.stock_message}, dispatch: {detail.dispatch_time_days} days")
print(f" Images: {len(detail.image_urls)}")
for opt in detail.options:
print(f" Option '{opt.name}': {[v.name for v in opt.values]}")
# Point lookup by a known product_id, with typed error handling.
try:
product = client.products.get(product_id=hit.product_id) if hit else client.products.get(product_id=19)
print(f"\nLooked up: {product.name}")
except ProductNotFound:
print("Product not found on the site.")
print("\nexercised: categories.list / category.products.list / product_summaries.search / details / products.get")
Searches the whole Curtfire catalogue by keyword and returns one page of product summary cards (one record per product) with price in ZAR, stock flag, thumbnail, vendor and rating counts. An empty keyword lists the entire catalogue. Results are paginated: page (1-based, default 1) and page_size (default 24, clamped to 100) are read from the caller; total_count is the site's count of matching products and has_more tells whether a further page exists. sort selects the site's own ordering menu. vendor_id restricts results to a single marketplace vendor (vendor_id as emitted on product cards; products with no vendor are site-owned). A keyword with no matches returns an empty products array with total_count 0. One upstream request per call.
| Param | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| sort | string | Result ordering, mirroring the site's sort menu. |
| keyword | string | Free-text search term matched against product names and descriptions. Empty = list all products. |
| page_size | integer | Products per page; values above 100 are clamped to 100. |
| vendor_id | integer | Restrict to products sold by this marketplace vendor (vendor_id from product cards). Omitted = all vendors. |
{
"type": "object",
"fields": {
"page": "integer, the page returned (1-based)",
"sort": "the sort code applied",
"has_more": "boolean, true when a further page exists",
"products": "array of product summary cards: product_id (integer, use with get_product), name, short_description (nullable), sku (nullable), slug (nullable), url, price (number, ZAR), old_price (nullable pre-discount price), discount_percentage (nullable integer), currency, in_stock (boolean), image_url, rating_average, rating_count, vendor_id (nullable integer), vendor_name (nullable), has_required_options (boolean: product needs a variant choice)",
"page_size": "integer, effective page size after clamping",
"total_count": "integer, site-reported number of products matching the query across all pages"
},
"sample": {
"data": {
"page": 1,
"sort": "position",
"has_more": false,
"products": [
{
"sku": null,
"url": "https://curtfire.co.za/product/19/childrens-smart-watch",
"name": "Children's smart watch",
"slug": "childrens-smart-watch",
"price": 569,
"currency": "ZAR",
"in_stock": true,
"image_url": "https://portal.curtfire.co.za/images/thumbs/0000101_childrens-smart-watch_300.jpeg",
"old_price": null,
"vendor_id": 1,
"product_id": 19,
"vendor_name": "Curtfire",
"rating_count": 0,
"rating_average": 0,
"short_description": null,
"discount_percentage": null,
"has_required_options": true
}
],
"page_size": 24,
"total_count": 1
},
"status": "success"
}
}About the Curtfire API
Search and Browse the Catalogue
The search_products endpoint accepts a keyword string matched against product names and descriptions. Leaving keyword empty returns the full catalogue. Results are paginated using page (1-based) and page_size (clamped to 100). Each product summary card in the products array includes product_id, name, short_description, sku, price in ZAR, in_stock flag, thumbnail URL, vendor, and rating counts. A total_count field reports the site's total matching products across all pages, and has_more indicates whether a subsequent page exists. You can also restrict results to a single seller using the vendor_id parameter.
Category Navigation
list_categories returns every category in the Curtfire hierarchy as a flat list. Each entry includes category_id, name, slug, url, and parent_category_id — where 0 marks a top-level category and any non-zero value points to the parent's category_id. Feed any category_id into list_category_products to retrieve paginated product summary cards scoped to that category. The same sort, page, and page_size parameters available in search_products work here too.
Full Product Details
get_product takes a single product_id (as returned by search_products or list_category_products) and returns the complete product record. Key fields include price and old_price (both in ZAR), currency (ISO code ZAR), in_stock, sku, gtin, slug, url, and a gallery array of image URLs. The options array exposes variant groups — each with option_id, name, prompt, is_required, and a values array carrying value_id, name, color_rgb, and price_adjustment. Dispatch lead time in days and a stock message are also included.
The Curtfire API is a managed, monitored endpoint for curtfire.co.za — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when curtfire.co.za 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 curtfire.co.za 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?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Sync Curtfire ZAR prices and stock status into a price-comparison tool targeting South African shoppers.
- Build a category-aware product feed by walking the category tree from list_categories and paginating list_category_products for each leaf node.
- Monitor old_price vs price fields from get_product to detect active discounts across the catalogue.
- Filter search_products by vendor_id to aggregate all listings from a specific Curtfire marketplace seller.
- Populate a product configurator by reading the options and values arrays from get_product to surface variant choices.
- Track rating counts over time from search_products summary cards to identify trending or newly reviewed products.
- Index Curtfire product names, descriptions, and GTINs for a local South African shopping search engine.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.