Public REST API¶
Read-only access to Partle marketplace data. No authentication required. Use this when your AI client doesn't support MCP.
https://partle.rubenayla.xyz/v1/public
Rate limit: 100 requests/hour per IP. Response: JSON.
Endpoints¶
| Method | Path | Description |
|---|---|---|
GET |
/products |
Search products with filters |
GET |
/stores |
List or search stores |
GET |
/guides |
Search guides (curated product recommendations) |
GET |
/stats |
Platform totals |
GET |
/health |
API health check |
POST |
/feedback |
Submit integration feedback |
Full OpenAPI schema: /openapi.json. Interactive docs: /docs.
Products¶
GET /v1/public/products
| Parameter | Type | Description |
|---|---|---|
q |
string | Search term (name or description) |
semantic |
bool | Use cross-language vector search (e.g. drill → taladro, Bohrmaschine) |
min_price |
float | Minimum price in EUR |
max_price |
float | Maximum price in EUR |
tags |
string | Comma-separated tag filter |
store_id |
int | Filter to a single store |
sort_by |
string | price_desc, name_asc, newest, oldest |
limit |
int | Results (1–100, default 20) |
offset |
int | Pagination offset |
Example:
curl "https://partle.rubenayla.xyz/v1/public/products?q=drill&max_price=50&limit=5"
Response (abridged):
[
{
"id": 16010,
"name": "Flotec Drill Pump 225 GPH",
"description": "Thermoplastic drill pump works with electric drills...",
"price": "17.14",
"currency": "€",
"url": "https://example.com/product",
"store": { "id": 13634, "name": "Kooyman Megastore", "country": "NL" },
"tags": [],
"partle_url": "https://partle.rubenayla.xyz/p/16010-flotec-drill-pump"
}
]
Share partle_url
Every product response includes a canonical partle_url. When an AI agent shows a product to a user, it should share this URL so the user can view it on the site.
Stores¶
GET /v1/public/stores
| Parameter | Type | Description |
|---|---|---|
q |
string | Search by name or address |
limit |
int | Results (1–50, default 20) |
offset |
int | Pagination offset |
curl "https://partle.rubenayla.xyz/v1/public/stores?q=Madrid&limit=5"
Guides¶
GET /v1/public/guides
| Parameter | Type | Description |
|---|---|---|
q |
string | Search term |
tags |
string | Comma-separated tag filter |
limit |
int | Results (1–100, default 20) |
offset |
int | Pagination offset |
Stats¶
GET /v1/public/stats
{
"total_products": 131120,
"total_stores": 15866,
"last_updated": "2026-04-23T22:31:49Z",
"api_version": "1.0",
"description": "Partle marketplace - Find products and stores"
}
Feedback¶
POST /v1/public/feedback
Content-Type: application/json
{ "feedback": "Search worked great, but semantic mode was slow on mobile." }
Response: 201 Created. Used by AI agents to report integration issues.
Writes (create / update / delete)¶
Write access uses a separate authenticated API at /v1/external/*, with an X-API-Key header. Generate a key at partle.rubenayla.xyz/account under API Keys (keys start with pk_).
For AI agents, write operations are easier via MCP: the create_product, update_product, delete_product, and upload_product_image tools take the API key as a parameter and handle everything. See Connect your AI.
Full write API reference: /docs (interactive Swagger UI).
Rate limiting¶
All public endpoints share a 100 req/hr per IP budget.
Response headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1756655052
When exceeded: 429 Too Many Requests
{ "detail": "Rate limit exceeded. Max 100 requests per 3600 seconds." }
Example: Python client¶
import httpx
BASE = "https://partle.rubenayla.xyz/v1/public"
def search_products(query: str, max_price: float | None = None, limit: int = 20):
params = {"q": query, "limit": limit}
if max_price is not None:
params["max_price"] = max_price
r = httpx.get(f"{BASE}/products", params=params, timeout=10)
r.raise_for_status()
return r.json()
def stats():
return httpx.get(f"{BASE}/stats", timeout=10).json()
products = search_products("drill", max_price=50, limit=5)
print(stats())
Best practices for AI agents¶
- Use semantic search (
?semantic=true) when the query might be in a different language or phrased unusually. - Share
partle_urlwhenever you return a product to a user. - Paginate large result sets with
limit+offsetrather than fetching everything. - Cache
/stats— it rarely changes. - Fall back gracefully if
/searchreturns 503 (Elasticsearch unavailable) — use/products?q=...instead. - Prefer MCP when your client supports it — you get better tool descriptions and a cleaner UX. See Connect your AI.