The Spool List

Developer docs

The Spool List API

A REST API for Enterprise and Global subscribers: bulk-import machines and Forge listings into your own account from your systems. This page documents every endpoint that is live today. New endpoints are announced in the changelog.

Overview

Base URLhttps://api.thespoollist.com
FormatJSON request and response bodies (Content-Type: application/json)
AuthAPI key in the Authorization header — see Authentication
Who can use itAccounts on an Enterprise or Global subscription
Where to call it fromYour server. Browser requests from other websites are not allowed by the API's CORS policy, and an API key must never be shipped in client-side code.

Authentication

Create a key in the Developer panel of The Spool List app (Enterprise and Global accounts), or with POST /v1/api/keys. The full key is shown once, when it is created — only its 8-character prefix is stored in readable form, so copy it straight away.

Keys look like this:

spl_live_<8 hex characters>_<32 hex characters>

Send the key as a bearer token on every request:

curl https://api.thespoollist.com/v1/api/me \
  -H "Authorization: Bearer spl_live_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  • A missing or badly formed key returns 401 {"error":"Missing or malformed API key"}; an unknown or revoked key returns 401 {"error":"Invalid API key"}.
  • The account that owns the key must be on an Enterprise or Global subscription, otherwise 402 (see Errors).
  • After 20 failed authentication attempts from one IP address within 5 minutes, that address is locked out for 15 minutes (429 with a Retry-After header).
  • Revoking a key in the app or with DELETE /v1/api/keys/:id takes effect on the next request.

Scopes

Each key carries one or more scopes, chosen when it is created. Scopes are written with a colon (listings:write); the underscore form (listings_write) is accepted too.

ScopeUsed by
listings:writePOST /v1/api/machines/bulk, POST /v1/api/listings/bulk
listings:readReserved — no released endpoint requires it yet
jobs:readReserved — no released endpoint requires it yet
earnings:readReserved — no released endpoint requires it yet
webhooksReserved — webhooks are not available yet

GET /v1/api/me needs no scope. A request without a required scope returns 403 {"error":"Missing required scope: listings_write"}.

Rate limits

Limits apply per account — all of an account's keys share them.

SubscriptionPer minutePer day
Enterprise300 requests100,000 requests
Global1,000 requests500,000 requests

Every authenticated response carries the current state:

X-RateLimit-Limit-Minute: 300
X-RateLimit-Remaining-Minute: 299
X-RateLimit-Limit-Day: 100000
X-RateLimit-Remaining-Day: 99999

Each window starts with the first request after the previous window ended. When a limit is reached the API answers 429 with a Retry-After header (seconds) and a body such as {"error":"Rate limit exceeded (per-minute)","retry_after_sec":12}. Limits are hard caps; there are no overage charges.

Errors

Errors are JSON with an error string.

StatusMeaning
400The request body is invalid (for bulk endpoints: empty array, batch too large, or no valid rows — see each endpoint).
401Missing, malformed, unknown or revoked key.
402The account is not on an Enterprise or Global subscription. Body: {"error":"API access requires an Enterprise or Global subscription","current_tier":"…","upgrade_url":"…"}
403The key lacks a scope the endpoint requires.
429Rate limit reached, or too many failed authentication attempts. Wait for Retry-After seconds.
500Server error. Safe to retry GET requests; for bulk imports, check what was created before retrying.

Get the key's account

GET/v1/api/me

Returns the account that owns the key and the key's own prefix and scopes — a quick way to check a key works.

{
  "id": "1f0c…-uuid",
  "display_name": "Your shop name",
  "subscription_tier": "enterprise",
  "is_owner": true,
  "has_completed_onboarding": true,
  "key": { "prefix": "a1b2c3d4", "scopes": ["listings:write"] }
}

Bulk-register machines

POST/v1/api/machines/bulk

Scope listings:write. Adds up to 500 machines to the key's account in one request (body up to 1 MB). Same fields as the CSV import in the app. Every new machine starts with verification status pending, and is always added to the key's own account.

FieldType
template_idstringRequired
categorystringRequired
manufacturerstringRequired
modelstringRequired
model_numberstringOptional
nicknamestringOptional, up to 80 characters
capabilitiesstring[]Optional
is_skill_stationbooleanOptional, default false
curl -X POST https://api.thespoollist.com/v1/api/machines/bulk \
  -H "Authorization: Bearer $SPOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"machines":[{"template_id":"…","category":"three_d_printing","manufacturer":"Prusa","model":"MK4","capabilities":["pla","petg"]}]}'

Response 201:

{ "inserted": 1, "skipped": 0, "errors": [] }

Rows that fail validation are skipped and listed in errors as {"index": n, "reason": "…"}; the valid rows are still created. If no row is valid the response is 400 {"error":"no valid rows","errors":[…]}. More than 500 rows returns 400 with received set to the count sent.

Bulk-create Forge listings

POST/v1/api/listings/bulk

Scope listings:write. Creates up to 200 Forge listings on the key's account in one request (body up to 2 MB). Same fields as the CSV import in the app.

FieldType
titlestringRequired, stored up to 120 characters
descriptionstringRequired, stored up to 2,000 characters
price_centsintegerRequired, ≥ 0, in US cents
currencystringRequired, must be "USD" — Forge listings are priced and charged in US dollars only
categorystringRequired, one of miniatures, home_decor, cosplay, jewelry, gadgets, art, gifts, replacement, fashion, electronics, automotive, rc_drones, education, outdoor, other
materialstringRequired, up to 80 characters
photo_urlsstring[]Required: at least one https:// URL; up to 8 are kept and the first is the thumbnail
colorstringOptional, up to 40 characters
tagsstring[]Optional, up to 10
print_time_hoursnumberOptional
is_availablebooleanOptional, default true
allows_custom_ordersbooleanOptional, default false
curl -X POST https://api.thespoollist.com/v1/api/listings/bulk \
  -H "Authorization: Bearer $SPOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listings":[{"title":"Articulated dragon","description":"Print-in-place, 30 cm.","price_cents":2400,"currency":"USD","category":"miniatures","material":"PLA","photo_urls":["https://example.com/dragon.jpg"]}]}'

Response 201 has the same shape as machines: {"inserted": n, "skipped": m, "errors": [{"index": i, "reason": "…"}]}. The maker name and photo on each listing come from the account's profile.

Key management

These endpoints manage keys, so they are authenticated with the account's signed-in session token (the same bearer token the app uses), not with an API key — you cannot create your first key with a key. They also require an Enterprise or Global subscription (402 otherwise).

List keys

GET/v1/api/keys

Up to 50 keys, newest first: {"keys":[{"id","label","key_prefix","scopes","is_revoked","last_used_at","created_at"}]}. Full keys are never returned.

Create a key

POST/v1/api/keys

{ "label": "Inventory sync", "scopes": ["listings:write"] }

label (up to 80 characters) and at least one valid scope are required. Response 201:

{
  "key": "spl_live_a1b2c3d4_…",
  "metadata": { "id": "…", "label": "Inventory sync", "key_prefix": "a1b2c3d4", "scopes": ["listings_write"], "created_at": "…" },
  "note": "This is the only time the full key is shown. Copy it now — you won't be able to see it again."
}

An account can have up to 20 active keys; creating another returns 429 until one is revoked.

Revoke a key

DELETE/v1/api/keys/:id

Revokes one of the account's keys: {"revoked":{"id","key_prefix","is_revoked":true}}, or 404 if the key is not the account's. Revoking cannot be undone.

Health

GET/v1/health

Public, no key. Returns {"status":"ok", …, "timestamp":"…"} while the API is up — use it for uptime checks rather than an authenticated endpoint, so checks do not count against your rate limit.

Support

Questions about the API, or something here that does not match what you see: support@thespoollist.com.