Skip to content
← Back to Blog tutorials

Automate 3D model downloads for your game with a REST API

By BitSoul3D4 min read80 views

Downloading 40 props one at a time from a marketplace tab, saving each to the right folder, renaming files that all arrive as model.glb — that's an hour of clicking for work a script does in under two minutes. At the default page size of 24 results per call, browsing the full catalog by hand means paging through 36 screens before you've even started clicking downloads. BitSoul3D's REST API does the same job as the download button: three GET endpoints, one POST, one DELETE, and a single header. No OAuth flow, no SDK to install. Send X-API-Key on every authenticated call and get JSON back, or a binary GLB stream for the download endpoint. The catalog itself — 846 models right now, 747 of them covered by your monthly download quota — is searchable with no key at all.

Automate 3D model downloads for your game with a REST API

Get your API key

Your key lives on the account dashboard, shown once on signup and re-viewable there afterward. It's prefixed bsm_, and API access ships with the Studio tier. The same key authenticates every private endpoint below — there's no separate scope per call, so treat it like a password rather than a public identifier. If a key ends up committed to a public repo, hit Regenerate on the dashboard — the old key stops working the moment you do, no support ticket needed.

Search and filter models with the REST API

Search and filter models with the REST API — illustrated

GET /api/models takes four query params: q for free text, category (animals, architecture, characters, electronics, fantasy, food, furniture, industrial, misc, nature, vehicles, or weapons), page, and limit (max 100, default 24). Neither this endpoint nor GET /api/models/:id needs a key.

The response also carries a pagination object (page, limit, total, pages). At the max limit of 100, listing an 846-model catalog takes nine requests, not one — a real search script loops on page until it passes pagination.pages instead of assuming everything fits on one screen.

Filter before you loop, not after. The response carries a premium field: 0 means the model draws from your monthly quota, 1 means it's priced individually (check price_cents) and won't come out of that quota the same way. A batch job that doesn't check this field will happily queue up paywalled models next to free ones:

curl -s "https://bitsoulhosting.com/marketplace/api/models?category=weapons&limit=50" \
  | jq -r '.models[] | select(.premium==0) | "\(.id) \(.name)"'

That prints id/name pairs for every standard weapon model — Sci fi mercenary assault rifle among them, a 60,000-triangle mesh that's 9.3 MB as a GLB.

Download models and stay inside your quota

Download models and stay inside your quota — illustrated

Download models and stay inside your quota — illustrated

GET /api/models/:id/download is the authenticated call, and it counts against your plan's monthly credits. The mechanics are identical across plans — only the ceiling changes:

PlanMonthly download creditsPrice
Free2$0
Indie25$12/mo
Pro100$29/mo
StudioUnlimited$79/mo

A free account's two monthly downloads cover evaluation; commercial use is included with paid memberships — see pricing for the full breakdown.

Every plan shares the same three outcomes on this endpoint — 200 with the binary GLB, 401 for auth problems, 429 for quota problems — so a script only needs to branch on two failure cases, not a dozen. A missing or wrong key returns 401 with {"error":"API key required. Set X-API-Key header."}. Go past your ceiling and you get 429 with a quota object (used, limit, remaining) instead of a file, so check the status code before you assume the response body is a GLB:

import requests, pathlib

KEY, out = "YOUR_API_KEY", pathlib.Path("assets")
out.mkdir(exist_ok=True)
for mid, name in models:  # (id, name) pairs from the search step above
    r = requests.get(f"https://bitsoulhosting.com/marketplace/api/models/{mid}/download",
                      headers={"X-API-Key": KEY}, stream=True)
    if r.status_code == 429:
        print("quota hit:", r.json()["quota"]); break
    (out / f"{mid}.glb").write_bytes(r.content)

Eleven lines, and it fills an assets/ folder overnight instead of a browser tab you have to babysit through 40 clicks.

What breaks when you script this

The quota resets on the first of the month, not on a rolling 30-day window from your last download — a job that dies at credit 2 on the 28th runs clean again on the 1st, no waiting. GET /api/downloads/history (param limit, 1–200, default 50) is the fastest way to check what already came down before you re-run a job and burn credits on duplicates.

Favoriting has a similar trap: POST /api/favorites/:modelId caps the free tier at 10 saved models. Past that it returns 403 with upgrade_required:true in the body, not a silent no-op, so a script that ignores status codes will think every favorite succeeded when half of them didn't. DELETE /api/favorites/:modelId has no such cap.

Two more fields worth checking before you queue a batch: has_rigging and has_animations. Filtering on those client-side, alongside premium, keeps a batch job for a character-animation test from downloading a dozen static props when only three models in the results are actually rigged.

For the export side of this pipeline, batch-exporting GLBs from Blender and tracking the binaries in Git LFS cover what happens after the script writes a file to disk. If your engine needs a custom step on import, too, Godot's EditorImportPlugin picks up right where this leaves off.


This post is part of the Ultimate Guide to Free 3D Game Assets — BitSoul's complete reference for formats, texturing, rigging, optimization, and engine integration.


Need drop-in assets for this workflow? Grab the 82-model Vehicle Bundle on the BitSoul marketplace and drop them straight into your project.

Tags: vehicles

Skip the modeling — download it instead

A free BitSoul3D account gets you 2 GLB downloads every month for personal use plus 25 one-time AI Engine credits, no card required. PBR-textured GLB downloads with a full 3D preview before you buy, for Unreal, Unity, Godot or Blender — OBJ and 3D-printable STL come with any purchase or paid plan.

Browse 1,051 models — from $4.99 → or start free (2 downloads a month)