Skip to content
3D Asset Server

3D Asset Server API reference

One search API for free and paid 3D models, PBR materials, textures, HDRIs and game assets. Version 0.1.0, base URL https://3d.shep.bot. Machine-readable:OpenAPI 3.1 JSON. Want to send requests from the browser? Open theinteractive API playground.

  • Authentication: none on the public server. Self-hosted servers may require Authorization: Bearer <key> or x-api-key.
  • Rate limits: 120 requests per minute per client, announced in RateLimit-Policy / RateLimit headers; 429 comes with Retry-After. See versioning & rate limits.
  • Errors: JSON { "error": "message" } with a 4xx/5xx status.

Find assets across every source in one call.

GET/v1/searchSearch every source

Fans out to every enabled source in parallel (each with its own timeout), then merges, ranks and de-duplicates. A slow or failing source never fails the search: it shows up in providers with its status.

Parameters

NameInTypeDescription
qquerystringShort, concrete query.
typequerystringComma-separated asset types: model, texture, material, hdri, sprite, ui, audio, font, pack, other.
providersquerystringComma-separated source ids (see /v1/providers).
freequerybooleanOnly free assets.
downloadablequerybooleanOnly assets this server can download directly.
limitqueryintegerMax results (default 24).
offsetqueryintegerPer-source offset for paging (e.g. 24 for page 2).

Responses

  • 200Ranked results plus a per-source report.SearchResponseheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 400Invalid parameters or unknown source id.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 401API key required (self-hosted servers only).Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 429Rate limit exceeded. Wait Retry-After seconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy

Example

curl "https://3d.shep.bot/v1/search?q=low%20poly%20tree&type=model"

Assets

Details, file selection and downloads for a single asset.

GET/v1/assets/{id}Asset details with files

Full metadata, licence and every downloadable file for one asset.

Parameters

NameInTypeDescription
id *pathstringAsset id <provider>:<nativeId>, URL-encoded (: may stay as is). Take it from a search result.

Responses

  • 200The asset and its files.AssetDetailsheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 404Unknown asset.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 429Rate limit exceeded. Wait Retry-After seconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
  • 502The source site failed.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset

Example

curl "https://3d.shep.bot/v1/assets/polyhaven:ArmChair_01"
GET/v1/assets/{id}/filesPick the right files

Smart selection for a format and resolution (e.g. glTF with its .bin and textures, or a 2k PBR map set).

Parameters

NameInTypeDescription
id *pathstringAsset id <provider>:<nativeId>, URL-encoded (: may stay as is). Take it from a search result.
formatquerystringPreferred format or package. Closest match wins; omitted = best default for the asset type.
resolutionquerystringTexture/HDRI resolution. The closest available is used (default 2k).
mapsquerystringComma-separated texture map types for map sets, e.g. diff,nor_gl,rough,ao.
allquerybooleanReturn every file instead of the smart selection.

Responses

  • 200Selected files and total size.FileSelectionheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 404Unknown asset.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 429Rate limit exceeded. Wait Retry-After seconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy

Example

curl "https://3d.shep.bot/v1/assets/polyhaven:ArmChair_01/files?format=glb&resolution=1k"
GET/v1/assets/{id}/downloadDownload

A single self-contained file redirects (302) to the source CDN. Multi-file selections stream as one zip (e.g. glTF + .bin + textures, ready to drop into a project).

Parameters

NameInTypeDescription
id *pathstringAsset id <provider>:<nativeId>, URL-encoded (: may stay as is). Take it from a search result.
formatquerystringPreferred format or package. Closest match wins; omitted = best default for the asset type.
resolutionquerystringTexture/HDRI resolution. The closest available is used (default 2k).
mapsquerystringComma-separated texture map types for map sets, e.g. diff,nor_gl,rough,ao.
allquerybooleanReturn every file instead of the smart selection.

Responses

  • 200Zip bundle.string (binary)headers: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 302Redirect to the single file.headers: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 404Unknown asset or no file matches.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 409The source has no direct downloads; url is its page.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 429Rate limit exceeded. Wait Retry-After seconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy

Example

curl -L -O "https://3d.shep.bot/v1/assets/polyhaven:ArmChair_01/download?format=glb&resolution=1k"

Sources

The asset sites this server searches.

GET/v1/providersList sources

Every asset site with what it carries, pricing, licence and whether files can be downloaded directly.

Responses

  • 200Sources.objectheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 429Rate limit exceeded. Wait Retry-After seconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy

Example

curl "https://3d.shep.bot/v1/providers"
GET/v1/catalogCatalog census

How many assets every source holds, counted once a day: listings per source, by asset type, licence and the source's own categories, free counts, listings added in the last 30 days, and highlights such as the most downloaded asset. atLeast: true marks lower bounds (sources that cap their counts). Sources whose count failed today keep their last good numbers with stale. The same file is at /catalog.json; one point per day is in /catalog-history.json.

Responses

  • 200Catalog census.Catalogheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 429Rate limit exceeded. Wait Retry-After seconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy

Example

curl "https://3d.shep.bot/v1/catalog"
GET/v1/statsUsage statistics

Aggregate usage of this server: searches by surface (web, API, MCP), downloads, MCP tool calls, the client families and asset types searched most, and per-source health (success rate, p50/p95 latency). Counts come from Prometheus (source: prometheus, last 24 hours and 7 days) or, when it is unavailable, from this process since it started (source: process). No queries, IPs or user agents are exposed. Cached for 60 seconds.

Responses

  • 200Usage statistics.Statsheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 429Rate limit exceeded. Wait Retry-After seconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy

Example

curl "https://3d.shep.bot/v1/stats"

MCP

Model Context Protocol endpoint for AI agents.

POST/mcpMCP endpoint (Streamable HTTP)

Stateless Model Context Protocol endpoint for AI agents. Tools: search_assets, get_asset, list_providers. Point any MCP client at this URL; see /docs/mcp for per-client setup.

Responses

  • 200JSON-RPC 2.0 response.objectheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
  • 429Rate limit exceeded. Wait Retry-After seconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy

Example

curl -X POST "https://3d.shep.bot/mcp" \
  -H "content-type: application/json" -H "accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_assets","arguments":{"query":"sunset hdri","types":["hdri"]}}}'

System

Health and machine-readable descriptions.

GET/healthHealth check

Responses

  • 200OKobject

Example

curl "https://3d.shep.bot/health"
GET/openapi.jsonThis OpenAPI document

Responses

  • 200OpenAPI 3.1object

Example

curl "https://3d.shep.bot/openapi.json"

Schemas

AssetType

One of: model, texture, material, hdri, sprite, ui, audio, font, pack, other

CountWithBound

count *integer
atLeastbooleanThe count is a lower bound.

SourceCensus

id *string
name *string
homepage *string (uri)
total *integerListings on the source (free and paid).
atLeastboolean
freeinteger
byType *object
byLicenseobject
categoriesobject
unit"assets" | "packs"
addedLast30Daysinteger
downloadsintegerTotal downloads, when the source publishes them.
highlightsobject[]
method *stringHow the source was counted.
countedAt *string (date-time)
staleobject

Catalog

countedAt *string (date-time)
totals *object
byType *object
byLicenseobject
sources *SourceCensus[]
linkedobject[]

UsageWindow

key *string24h, 7d, or process (since the last restart).
label *string
searches *integer
searchesWithResults *integer
bySurface *object
assetViews *integer
downloads *integer
toolCalls *integerMCP tool calls.
pageViews *integerWebsite pages served.

Ranked

name *string
count *integer

ProviderHealth

provider *string
requests *integerSearches that reached the source.
ok *integer
errors *integer
timeouts *integer
okRate *number | null
p50Ms *integer | null
p95Ms *integer | null

Stats

generatedAt *string (date-time)
source *"prometheus" | "process"
sincestring (date-time)Start of counting for source: process.
windows *UsageWindow[]
breakdownLabel *stringPeriod covered by clients, tools and assetTypes.
clients *Ranked[]Searches by client family (claude-code, cursor, browser, curl…).
tools *Ranked[]MCP tool calls by tool.
assetTypes *Ranked[]Searches by asset type filter (any = no filter).
providers *ProviderHealth[]Per-source health over the last 24 hours.
catalog *object

License

name *stringCC0, CC-BY-4.0, Royalty Free, ...
urlstring (uri)
commercialUseboolean
attributionRequiredboolean

Price

free *boolean
amountnumber
currencystring

Asset

id *stringGlobally unique <provider>:<nativeId>.
provider *string
nativeId *string
title *string
descriptionstring
type *AssetType
tags *string[]
categoriesstring[]
url *string (uri)The asset's page on the source site.
thumbnailUrlstring (uri)
authorstring
licenseLicense
pricePrice
formatsstring[]Known file formats (glb, fbx, blend, exr, ...).
resolutionsstring[]Texture resolutions (1k, 2k, 4k, ...).
polyCountinteger
animatedboolean
riggedboolean
downloadable *booleanTrue when this server can fetch the files directly.
createdAtstring
scorenumberRelevance 0..1 assigned by the ranker.

AssetFile

url *string (uri)
filename *string
format *string
resolutionstring
mapTypestringTexture map role: diffuse, normal, roughness, ...
sizeBytesinteger
groupstringPackage grouping: gltf, blend, textures, archive, ...
includesobject[]Companion files that must sit next to this one (e.g. a .gltf's .bin and textures).
requiresAuthbooleanNeeds a login or purchase on the source site.

AssetDetails

Asset & object

ProviderReport

provider *string
name *string
status *"ok" | "error" | "timeout" | "skipped" | "link"link = the site blocks bots; use searchUrl to run the same search there.
count *integer
totalinteger
searchUrlstring (uri)
errorstring
tookMs *integer

SearchResponse

query *string
typesAssetType[]
results *Asset[]Merged, ranked and de-duplicated.
providers *ProviderReport[]One status line per source.

Provider

id *string
name *string
homepage *string (uri)
description *string
assetTypes *AssetType[]
access *"api" | "scrape" | "link"
pricing *"free" | "freemium" | "paid"
licenseLicense
supportsDownload *boolean
enabledboolean

FileSelection

id *string
licenseLicense
totalBytesinteger
files *AssetFile[]

Error

error *string
urlstring (uri)
retryAfterinteger

AI agent? This page is also available as markdown.