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>orx-api-key. - Rate limits: 120 requests per minute per client, announced in
RateLimit-Policy/RateLimitheaders;429comes withRetry-After. See versioning & rate limits. - Errors: JSON
{ "error": "message" }with a 4xx/5xx status.
Search
Find assets across every source in one call.
/v1/searchSearch every sourceFans 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
| Name | In | Type | Description |
|---|---|---|---|
| q | query | string | Short, concrete query. |
| type | query | string | Comma-separated asset types: model, texture, material, hdri, sprite, ui, audio, font, pack, other. |
| providers | query | string | Comma-separated source ids (see /v1/providers). |
| free | query | boolean | Only free assets. |
| downloadable | query | boolean | Only assets this server can download directly. |
| limit | query | integer | Max results (default 24). |
| offset | query | integer | Per-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-Reset400Invalid parameters or unknown source id.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset401API key required (self-hosted servers only).Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.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.
/v1/assets/{id}Asset details with filesFull metadata, licence and every downloadable file for one asset.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Asset 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-Reset404Unknown asset.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy502The source site failed.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
Example
curl "https://3d.shep.bot/v1/assets/polyhaven:ArmChair_01"/v1/assets/{id}/filesPick the right filesSmart selection for a format and resolution (e.g. glTF with its .bin and textures, or a 2k PBR map set).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Asset id <provider>:<nativeId>, URL-encoded (: may stay as is). Take it from a search result. |
| format | query | string | Preferred format or package. Closest match wins; omitted = best default for the asset type. |
| resolution | query | string | Texture/HDRI resolution. The closest available is used (default 2k). |
| maps | query | string | Comma-separated texture map types for map sets, e.g. diff,nor_gl,rough,ao. |
| all | query | boolean | Return every file instead of the smart selection. |
Responses
200Selected files and total size.FileSelectionheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset404Unknown asset.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://3d.shep.bot/v1/assets/polyhaven:ArmChair_01/files?format=glb&resolution=1k"/v1/assets/{id}/downloadDownloadA 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
| Name | In | Type | Description |
|---|---|---|---|
| id * | path | string | Asset id <provider>:<nativeId>, URL-encoded (: may stay as is). Take it from a search result. |
| format | query | string | Preferred format or package. Closest match wins; omitted = best default for the asset type. |
| resolution | query | string | Texture/HDRI resolution. The closest available is used (default 2k). |
| maps | query | string | Comma-separated texture map types for map sets, e.g. diff,nor_gl,rough,ao. |
| all | query | boolean | Return every file instead of the smart selection. |
Responses
200Zip bundle.string (binary)headers: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset302Redirect to the single file.headers: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset404Unknown asset or no file matches.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset409The source has no direct downloads;urlis its page.Errorheaders: RateLimit, RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset429Rate limit exceeded. WaitRetry-Afterseconds.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.
/v1/providersList sourcesEvery 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-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://3d.shep.bot/v1/providers"/v1/catalogCatalog censusHow 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-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://3d.shep.bot/v1/catalog"/v1/statsUsage statisticsAggregate 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-Reset429Rate limit exceeded. WaitRetry-Afterseconds.Errorheaders: Retry-After, RateLimit, RateLimit-Policy
Example
curl "https://3d.shep.bot/v1/stats"MCP
Model Context Protocol endpoint for AI agents.
/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-Reset429Rate limit exceeded. WaitRetry-Afterseconds.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.
/healthHealth checkResponses
200OKobject
Example
curl "https://3d.shep.bot/health"/openapi.jsonThis OpenAPI documentResponses
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 | |
| atLeast | boolean | The count is a lower bound. |
SourceCensus
| id * | string | |
| name * | string | |
| homepage * | string (uri) | |
| total * | integer | Listings on the source (free and paid). |
| atLeast | boolean | |
| free | integer | |
| byType * | object | |
| byLicense | object | |
| categories | object | |
| unit | "assets" | "packs" | |
| addedLast30Days | integer | |
| downloads | integer | Total downloads, when the source publishes them. |
| highlights | object[] | |
| method * | string | How the source was counted. |
| countedAt * | string (date-time) | |
| stale | object |
Catalog
| countedAt * | string (date-time) | |
| totals * | object | |
| byType * | object | |
| byLicense | object | |
| sources * | SourceCensus[] | |
| linked | object[] |
UsageWindow
| key * | string | 24h, 7d, or process (since the last restart). |
| label * | string | |
| searches * | integer | |
| searchesWithResults * | integer | |
| bySurface * | object | |
| assetViews * | integer | |
| downloads * | integer | |
| toolCalls * | integer | MCP tool calls. |
| pageViews * | integer | Website pages served. |
Ranked
| name * | string | |
| count * | integer |
ProviderHealth
| provider * | string | |
| requests * | integer | Searches 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" | |
| since | string (date-time) | Start of counting for source: process. |
| windows * | UsageWindow[] | |
| breakdownLabel * | string | Period 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 * | string | CC0, CC-BY-4.0, Royalty Free, ... |
| url | string (uri) | |
| commercialUse | boolean | |
| attributionRequired | boolean |
Price
| free * | boolean | |
| amount | number | |
| currency | string |
Asset
| id * | string | Globally unique <provider>:<nativeId>. |
| provider * | string | |
| nativeId * | string | |
| title * | string | |
| description | string | |
| type * | AssetType | |
| tags * | string[] | |
| categories | string[] | |
| url * | string (uri) | The asset's page on the source site. |
| thumbnailUrl | string (uri) | |
| author | string | |
| license | License | |
| price | Price | |
| formats | string[] | Known file formats (glb, fbx, blend, exr, ...). |
| resolutions | string[] | Texture resolutions (1k, 2k, 4k, ...). |
| polyCount | integer | |
| animated | boolean | |
| rigged | boolean | |
| downloadable * | boolean | True when this server can fetch the files directly. |
| createdAt | string | |
| score | number | Relevance 0..1 assigned by the ranker. |
AssetFile
| url * | string (uri) | |
| filename * | string | |
| format * | string | |
| resolution | string | |
| mapType | string | Texture map role: diffuse, normal, roughness, ... |
| sizeBytes | integer | |
| group | string | Package grouping: gltf, blend, textures, archive, ... |
| includes | object[] | Companion files that must sit next to this one (e.g. a .gltf's .bin and textures). |
| requiresAuth | boolean | Needs 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 | |
| total | integer | |
| searchUrl | string (uri) | |
| error | string | |
| tookMs * | integer |
SearchResponse
| query * | string | |
| types | AssetType[] | |
| 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" | |
| license | License | |
| supportsDownload * | boolean | |
| enabled | boolean |
FileSelection
| id * | string | |
| license | License | |
| totalBytes | integer | |
| files * | AssetFile[] |
Error
| error * | string | |
| url | string (uri) | |
| retryAfter | integer |
AI agent? This page is also available as markdown.