Get 22 packs worth $978. Yours forever for $197 πŸ‘‰11Β days10Β hours56Β min21Β secClaim Deal - Just $197!
API

API authentication and keys

How API keys work: creating them, scopes, expiry, revoking, and how they differ from your TJA_ license key.

DX
Developer Experience Team
Updated Aug 18, 2026 Β· 6 min read
On this page (10)

Every authenticated call to /api/v1 carries an API key. A key stands in for your account the way a browser session does, but it is meant for scripts: no cookies, no sign-in page, no expiry unless you ask for one.

Keys are created and revoked in Account β†’ Connections, behind the Create API key button in the API keys section of that tab.

Sending the key#

Preferred β€” a bearer token:

bearer.sh
curl -s https://threejsassets.com/api/v1/me \
  -H "Authorization: Bearer tja_live_…"

Equivalent β€” the X-API-Key alias, for clients that reserve Authorization for something else:

alias.sh
curl -s https://threejsassets.com/api/v1/me \
  -H "X-API-Key: tja_live_…"

If both are present, the Authorization header wins. Send the key as a header only: never in a query string, never in client-side JavaScript, never committed to a repository.

An API key is not your TJA_ license key#

These are two different credentials and they are not interchangeable. This is the single most common mix-up, so it is worth being blunt about:

API keyLicense key
Looks liketja_live_…TJA_XXXX-XXXX-…
Identifiesyour accountone purchase
Used with/api/v1/*, as a header/api/download, in the JSON body
Created byyou, in Connectionsissued automatically with an order
How manyup to 10 at a timeone per order

Passing a TJA_ license key as Authorization: Bearer does not work. It is rejected before any lookup happens and you get:

wrong-credential.json
{
  "error": {
    "code": "invalid_api_key",
    "message": "That API key isn't valid. Check it was copied in full, or create a new one in your account's Connections tab.",
    "request_id": "5f3c9a10-2d6b-4b2e-9f77-1c0a8de41b52"
  }
}

If you see invalid_api_key and your credential starts with TJA_, you are on the wrong endpoint: license keys belong to the older /api/download route described in Downloading your packs. The reverse also holds β€” an API key is not accepted there.

The API never returns a license key in full. /v1/orders shows a masked preview only.

The key is shown exactly once#

When you create a key, the full value appears in the create dialog, with a Copy button next to it. It is stored only as a hash, so nobody β€” including support β€” can display it again once you close that dialog.

If you lose a key, revoke it and create a replacement. There is no "show key" and no recovery.

A key looks like this:

anatomy
tja_live_9f2cKp3xQm7RvL0aZs4Td8Bn1YhE6Wug_4kR7pq
β””β”€β”€β”€β”¬β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”¬β”€β”€β”˜
 prefix          random secret          checksum

The tja_live_ prefix makes keys easy to spot in a config file or a secret scanner. The trailing checksum catches a truncated copy-paste before anything else is checked.

Scopes#

Each key carries a set of scopes. Both are selected by default, which is what most people want; narrowing them is how you make a key that is worthless to a thief.

ScopeGrants
catalog:read/v1/me, /v1/packs, /v1/assets, /v1/orders, /v1/products, /v1/products/:slug
downloads:read/v1/packs/:slug/download, /v1/assets/:slug/download, /v1/products/:slug/download, and all three icon routes β€” /v1/icons/:name, /v1/icons/:name/download, /v1/icons/library

/v1/icons/:name is a metadata route that needs the download scope, which looks odd until you see why: its response can carry the icon's SVG, and an SVG is the artwork. Delivering bytes is what downloads:read means everywhere else, so it means it there too. For metadata alone, the public /v1/catalog/icons needs no key at all.

A key with only catalog:read can inventory your library but cannot pull a single byte of a file. Calling a download endpoint with it returns 403 insufficient_scope:

insufficient-scope.json
{
  "error": {
    "code": "insufficient_scope",
    "message": "This key is missing the \"downloads:read\" scope. Create a new key with it enabled.",
    "request_id": "5f3c9a10-2d6b-4b2e-9f77-1c0a8de41b52"
  }
}

Scopes cannot be edited after creation. To change them, create a new key and revoke the old one.

Expiry#

When you create a key you choose how long it lives:

  • Never expires (the default)
  • 90 days
  • 1 year

A key with an expiry stops working the moment it passes β€” calls return 401 expired_api_key. Fourteen days before that happens we email you, so a build server does not fail at 3am with no warning.

Pick a TTL for keys you hand to someone else or paste into a third-party CI system. Pick "never" for a key you control and can revoke yourself.

Revoking a key#

Open Account β†’ Connections and select Revoke next to the key. Revocation is immediate and permanent; the next call with that key returns 401 revoked_api_key.

Revoke a key when:

  • it has been committed to a repository or pasted into a chat;
  • a machine or contractor no longer needs access;
  • the Connections tab's Recent API downloads list shows a download you did not make.

Revoking a key never affects your purchases, your license keys, or your other keys. You can always revoke, even while API access is otherwise unavailable to your account.

Limits and good practice#

  • Up to 10 active keys per account. Revoke one to make room for another.
  • One key per machine or job, named after it. That way revoking is surgical, and /v1/me tells you which one is calling.
  • Store keys in a secret manager or environment variable, not in source. TJA_API_KEY is the name our examples use.
  • Rotate by overlap: create the new key, deploy it, then revoke the old one.

Who can use the API#

API access requires a purchase β€” buy any pack or lifetime access and the Connections tab opens up. If access is unavailable for your account you will see a notice explaining why in the Connections tab, and calls return 403 api_disabled or 403 not_eligible. Existing keys are left intact in that case; they simply fail until access returns.

Partner access#

Listing our catalog on your own site needs no key and no account at all β€” the public /v1/catalog/* endpoints are open, as the endpoint reference explains. What listings do need is a visible credit: "by ThreeJS Assets" on each card is the style we prefer, and a single "Assets by ThreeJS Assets" per page also works β€” both are shown, with copy-paste snippets, on threejsassets.com/partner. A key only enters the picture when you want to download or import actual model files, which live on the authenticated /v1/assets routes.

If you are on a free account and want that, request access through the form on threejsassets.com/partner. Approval is manual β€” a person reads every request and replies by email, so there is no instant grant. Once you are approved, the Connections tab opens up and you create keys the normal way; a free account's keys cover free-tier files only.

Next steps#

Still stuck?

Ask us directly β€” we answer support mail ourselves.

Contact support
Share
API authentication and keys β€” threejsassets.com