Loading...
Loading...
Use this skill whenever an LLM agent needs to search, browse, or download 3D models from Poly Pizza (poly.pizza) using their REST API. Triggers on any task involving: finding free low-poly 3D models, searching the Poly Pizza catalogue, fetching model metadata or download URLs, retrieving popular models, or downloading .glb files from Poly Pizza. Use this skill proactively whenever the agent needs to obtain 3D assets programmatically, even if the user just says "find me a 3D model of X" without mentioning Poly Pizza by name.
npx skill4agent add editframe/skills poly-pizza-apiPOLY_PIZZA_KEYX-Auth-Token: <your_api_key>https://api.poly.pizza/v1/GET /search/{query}| Param | Type | Default | Description |
|---|---|---|---|
| integer | 12 | Max results to return (max ~50) |
| string | — | Pagination cursor from a previous response |
| string | | File format filter ( |
| boolean | — | Filter to only animated models |
| string | — | Triangle count range, e.g. |
GET https://api.poly.pizza/v1/search/tree?limit=5
X-Auth-Token: your_key_here{
"cursor": "some_cursor_string_or_null",
"results": [
{
"ID": "5EGWBMpuXq",
"Title": "Oak Tree",
"Description": "A simple low poly oak tree",
"Creator": {
"Username": "someartist",
"PURL": "https://poly.pizza/u/someartist"
},
"Thumbnail": "https://...jpg",
"Download": "https://...glb",
"DownloadFBX": "https://...fbx",
"Licence": "CC-BY 4.0",
"Tags": ["nature", "tree", "foliage"],
"TriangleCount": 320,
"Animated": false,
"PublishedAt": "2021-08-15T04:32:11.000Z"
}
// ... more results
]
}GET /popularlimitcursorformatanimatedtricountGET https://api.poly.pizza/v1/popular?limit=10
X-Auth-Token: your_key_hereGET /model/{id}GET https://api.poly.pizza/v1/model/5EGWBMpuXq
X-Auth-Token: your_key_hereresultsDownload.glbimport requests
# First, search for the model
headers = {"X-Auth-Token": api_key}
resp = requests.get("https://api.poly.pizza/v1/search/chair", headers=headers, params={"limit": 1})
model = resp.json()["results"][0]
# Then download the .glb directly
glb_bytes = requests.get(model["Download"]).content
with open(f"{model['Title']}.glb", "wb") as f:
f.write(glb_bytes)| License | Requirements |
|---|---|
| CC0 | No attribution required — public domain |
| CC-BY 4.0 | Must credit the creator. Format: |
model.Licence"Oak Tree" by someartist (https://poly.pizza/u/someartist) CC-BY 4.0cursor?cursor=<value>results = []
cursor = None
while True:
params = {"limit": 24}
if cursor:
params["cursor"] = cursor
data = requests.get(url, headers=headers, params=params).json()
results.extend(data["results"])
cursor = data.get("cursor")
if not cursor:
break| Status | Meaning |
|---|---|
| 200 | OK |
| 401 | Missing or invalid API key |
| 404 | Model ID not found |
| 429 | Rate limit exceeded — back off |
| 500 | Server error — retry |
GET /search/{keyword}?limit=5TriangleCountimport requests, os
def fetch_model(api_key: str, keyword: str, out_dir: str) -> dict:
headers = {"X-Auth-Token": api_key}
r = requests.get(
f"https://api.poly.pizza/v1/search/{keyword}",
headers=headers,
params={"limit": 1}
)
r.raise_for_status()
results = r.json().get("results", [])
if not results:
raise ValueError(f"No models found for '{keyword}'")
model = results[0]
glb = requests.get(model["Download"])
glb.raise_for_status()
safe_name = model["Title"].replace(" ", "_")
path = os.path.join(out_dir, f"{safe_name}.glb")
with open(path, "wb") as f:
f.write(glb.content)
attribution = None
if "CC-BY" in model.get("Licence", ""):
attribution = (
f'"{model["Title"]}" by {model["Creator"]["Username"]} '
f'({model["Creator"]["PURL"]}) {model["Licence"]}'
)
return {"path": path, "model": model, "attribution": attribution}.glbDownloadFBXThumbnail