tinymodels

API

Read-only JSON over the same catalogue the site shows. No key, no account, no writes — every write is a 404. Absolute URLs come back in the responses, so a link from the API is directly usable.

read-only no key JSON

Quick start

BASE=https://tinymodels.co

# what is in the catalogue
curl -s "$BASE/api/models" | jq '.total, .models[].slug'

# the video models only
curl -s "$BASE/api/models?task=video-classification" | jq '.models[].slug'

# everything you need to fetch and verify one model
curl -s "$BASE/api/models/all-minilm-l6-v2" | jq '{sha256, download_filename, download_url}'

GET /api/models

Lists the catalogue. Every parameter is optional and they combine:

parametervaluesmeaning
qany textSubstring match, case-insensitive, across the name, the one-line summary and the whole model card.
tasktask slugExact match, e.g. text-generation, video-classification. Browse the catalogue for the full list.
formatformat slugExact match, e.g. safetensors, gguf, mlx.
licencelicence slugExact match, e.g. apache-2.0, mit, cc-by-nc-4.0.
sizeunder-100mb · 100mb-500mb · 500mb-1gb · over-1gbA range on the file size, not an exact value.
sortrecency · downloads · size-asc · size-descDefaults to recency.
limit1–100Default 24, clamped at 100.
offset0 and upFor paging. `total` in the response tells you how many there are.

The response wraps the rows with the query that produced them:

{
  "total": 12,     // matching the filters, ignoring limit and offset
  "limit": 24,
  "offset": 0,
  "sort": "recency",
  "models": [ … ]
}

GET /api/models/<slug>

A single model object, unwrapped:

{
  "slug": "all-minilm-l6-v2",
  "name": "sentence-transformers/all-MiniLM-L6-v2",
  "summary": "The 22M-parameter sentence embedder that quietly powers a large share of local search.",
  "task": "sentence-similarity",
  "format": "safetensors",
  "parameters": 22713728,
  "file": { "name": "model.safetensors", "bytes": 90868376 },
  "download_filename": "all-MiniLM-L6-v2.safetensors",
  "licence": "apache-2.0",
  "upstream": {
    "repo": "https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2",
    "path": "model.safetensors"
  },
  "sha256": "53aa51172d142c89d9012cce15ae4d6cc0ca6895895114379cacb4fab128d9db",
  "sha256_source": "upstream",
  "mirrored_locally": false,
  "download_url": "…/models/all-minilm-l6-v2/download",
  "page_url": "…/models/all-minilm-l6-v2",
  "checksum_url": "…/models/all-minilm-l6-v2/checksum",
  "downloads": 2,
  "added_at": "2026-08-03T20:14:21.719Z",
  "source": "seed",
  "bench": [
    {
      "metric": "Encoding speed",
      "value": 14200,
      "unit": "sentences/s",
      "hardware": "NVIDIA V100 GPU",
      "source": "https://www.sbert.net/docs/sentence_transformer/pretrained_models.html",
      "note": "the sentence-transformers model table's own definition of its speed column"
    }
  ]
}

The fields:

fieldvaluesmeaning
slugstringStable identifier, used in every URL for this model.
namestringorg/model, as the publisher writes it.
summarystringOne line. May be empty.
taskstringWhat the model does.
formatstringsafetensors, gguf, mlx, onnx, pytorch…
parametersnumber | nullParameter count, or null if the publisher does not state one.
file{ name, bytes }The publisher's own filename and the exact size in bytes.
download_filenamestringWhat the file saves as. Differs from file.name when the publisher's name is generic, so several models can share a folder.
licencestringAs the publisher declares it. Check it — some are non-commercial.
upstream{ repo, path } | nullWhere the bytes actually come from.
sha25664 hex charsThe digest to verify against.
sha256_sourceupstream · local`upstream` means the publisher's own record of that file (Hugging Face's LFS object id). `local` means this hub computed it from bytes it stored.
mirrored_locallybooleanWhether this hub holds the bytes. Always false for the curated catalogue.
download_urlstringThe stable download URL. Absolute, so it is copy-pasteable.
page_urlstringThe model page.
checksum_urlstringThe checksum page.
downloadsnumberTimes the hub served a download response for it.
bencharrayBenchmark figures: `{ metric, value, unit, hardware, source, note?, measured?, short? }`. Entries with `measured: true` were run by this hub on its own machine — the first is always milliseconds for one fixed input, which is what the catalogue column shows, and the second is the peak memory that run needed; `short` is the label the row uses. The rest are published results quoted from the source link. `hardware` is null when a source does not say what it ran on. Nothing is ever estimated: a figure is published, measured, or absent.
added_atISO 8601When the entry was added to the catalogue.
sourceseedHow the row got here. `seed` is the curated catalogue.

GET /health

Enough to check the service is alive and see what it is serving:

{
  "ok": true,
  "models": 12,
  "described_bytes": 5993076446,
  "port": 8080,
  "uptime_seconds": 849
}

Downloading and verifying from a script

Two endpoints do the work, and neither is JSON:

  • GET /models/<slug>/download — answers 302 to the publisher, with x-checksum-sha256 and a content-disposition naming the file
  • GET /models/<slug>/checksum — the digest as the default HTML page, ?format=txt for a sha256sum-compatible line, or ?format=json for { slug, file, upstream_file, bytes, sha256, sha256_source, download_url }
SLUG=all-minilm-l6-v2
curl -sL -o "$SLUG.safetensors" "$BASE/models/$SLUG/download"
curl -s "$BASE/models/$SLUG/checksum?format=txt" | shasum -a 256 -c -

Note that the digest header rides on the 302: a client that follows redirects never sees it. Take the expected digest from the API or the checksum endpoint and compare it yourself, as above. Verifying a download goes through this properly, including what a matching digest does and does not prove.

Writes

There are none. There is no upload endpoint, no authentication and no state a request can change. GET /upload, POST /upload and POST /api/upload all answer 404, and the proof run asserts that.