LibraryCraft
Item format and feed
How a library item is stored, and the API and open feed that apps and other libraries use to read it.
- The item file
- Fields
- Plan entities
- Linetypes by layer name
- Uploading a finished item
- Validation
- Library API
- Open feed
The item file
Every version of every item is one JSON document, item.json, media type application/json. It is called "CadCraft library item", format 1. A published version never changes; a changed item is a new version with a higher number.
- Every length is in millimeters and every angle in degrees.
- Z is up. The plan lies in X and Y at z = 0, and the insertion point is (0, 0, 0).
- The item's front faces −Y and its back is the +Y side: "back against a wall" means the plan's largest Y touches the wall.
{
"format": "cadcraft-library-item",
"format_version": 1,
"uuid": "…",
"version": 3,
"name": "Three-compartment sink, 90 in",
"kind": "equipment",
"category": "foodservice/sinks",
"description": "…",
"maker": "", "model": "",
"ifc": { "class": "IfcFurnishingElement", "predefined": "NOTDEFINED" },
"plan": {
"layers": [{ "name": "EQUIP", "color": 7 }],
"entities": [{ "type": "line", "layer": "EQUIP", "color": null, "x1": 0, "y1": 0, "x2": 100, "y2": 0 }]
},
"body": { "type": "box", "x": -1143, "y": -762, "z": 0, "w": 2286, "d": 762, "h": 1092 },
"clearances": [{ "name": "service", "x": 0, "y": -900, "z": 0, "w": 2286, "d": 900, "h": 2000 }],
"params": {
"width": 2286, "depth": 762, "height": 1092, "weight_kg": 0,
"elec": { "volts": "", "phase": "", "amps": "", "kw": "", "hp": "", "hz": "", "plug": "", "nema": "", "direct": "" },
"plumb": { "cw": "", "hw": "", "dd": "", "id": "", "gas": "" },
"remarks": ""
},
"source_attrs": { "ATTRIBUTE-TAG": "value as found in the file" },
"license": { "id": "CC-BY-4.0", "holder": "…", "attribution": "…", "url": "https://creativecommons.org/licenses/by/4.0/" },
"provenance": { "library": "librarycraft", "item": "…", "version": 3, "sha256": "…",
"source_file": "name.dwg", "source_sha256": "…", "published_at": "2026-10-10T00:00:00Z" }
}
Fields
| Field | What it holds |
|---|---|
format, format_version | Always "cadcraft-library-item" and 1. |
uuid, version | The item (stable across versions) and its version number, starting at 1. Filled by the library. |
name, description | Plain text. |
kind | equipment, furniture, fixture, symbol, detail. |
category | A taxonomy key such as foodservice/sinks. The full list is in the browse filter; there are 36 keys in 12 groups. |
maker, model | Empty for generic items. Never invented. |
ifc | The IFC class an app uses when it places the item in a model, with its predefined type. |
plan | The 2D symbol: layers (name, color) and entities (below). |
body | The 3D body: a box (x, y, z, w, d, h), a mesh (positions as x, y, z triples and indices as triangles), or null for a 2D symbol. |
clearances | Optional named boxes (service space, door swing) in the same coordinates. |
params | Width, depth, height (mm) and weight (kg) as numbers; electrical (volts, phase, amps, kW, HP, Hz, plug, NEMA, direct) and plumbing (cold and hot water, direct and indirect drain, gas) as text; remarks. All optional. |
source_attrs | Attributes exactly as found in the source file, as text, never edited. Item numbers and quantities are not part of an item: they belong to each placement. |
license | The license id (one of CC0-1.0, CC-BY-4.0, CC-BY-3.0, CC-BY-SA-4.0, MAKER-TERMS, TEAM-ONLY), the holder, the credit line and the license link. |
provenance | Where the file came from: the library, item and version, the sha256 of the item without its provenance, the source file's name and sha256, and when it was published. Filled by the library. |
Plan entities
Plan entities use the CadCraft drawing shapes. Each carries layer and color: null means by layer, 0 by block, 1 to 255 an indexed color, or "#rrggbb". Nested blocks are exploded when an item is made.
| Type | Fields |
|---|---|
line | x1, y1, x2, y2 |
circle | x, y, r |
arc | x, y, r, a0, a1 (degrees, counterclockwise) |
poly | pts: [[x, y, bulge?], …], closed |
ellipse | the CadCraft ellipse shape |
text | x, y, h, rot, value |
point | x, y |
hatch | boundary loops only, drawn solid |
Linetypes by layer name
Format 1 has no linetype field. The library and the apps draw each entity by its layer's name, so a plan symbol reads like a drawn plan without a format change. The first rule that matches wins; matching ignores case.
| Layer name contains | Drawn as | Use it for |
|---|---|---|
clear, swing or service | Light dotted line | Door swings, service space, access clearances |
hidden, dashed, above or below | Dashed line | Parts under a top (undershelves, legs), doors shown open below, items above the cut such as wall shelves |
center or centre | Centre line | Centre lines |
detail, thin or fine | Thin line | Ribs, grates, knobs, drains and other small detail |
| anything else | Object line | Everything else |
The closed shape whose extent matches the body's footprint (or the plan's extent when there is no box body) is drawn as the heavy outline and lightly filled. Text in a plan is shown only on the item page, never on cards: an item tag belongs to each placement, not to the symbol. The generic items use the layers EQUIP, EQUIP-DETAIL, EQUIP-HIDDEN, EQUIP-CENTER and EQUIP-SWING.
Uploading a finished item
Besides drawings and models, Upload takes a finished item: a .json file in format 1, as a maker's own tools can write it. It is checked with the same validation, without the fields the library fills in. uuid, version, license and provenance are left out if present, and you choose the license and declare the source on the form as with any upload. The file becomes one candidate, and its drawing is made from the item itself.
Validation
The library checks every version with the same rules the apps use:
- the required fields are present with the right types, and
format_versionis 1; - the category is in the taxonomy and the license is one of the allowed ids;
- numbers are finite and within ±10,000,000 mm;
- the JSON is at most 8 MB; a mesh has at most 200,000 triangles and every index is in range;
- text values are at most 500 characters and a plan has at most 50,000 entities;
- no keys outside the format, except under
source_attrs.
Uploaded source files can be up to 50 MB, with at most 500 blocks per upload.
Library API
The public parts answer without a key and send Access-Control-Allow-Origin: *. Every response is JSON in the envelope {"status": "success", "data": …}, or "status": "error" with a message. Team items appear only to a signed-in app whose user is a member of that team (Authorization: Bearer …).
List and search
GET https://getcadcraft.com/api/v1/library/items?q=&category=&kind=&license=&maker=&page=&per=
→ data: { items: [{ uuid, slug, name, kind, category, maker, model, license, version,
preview_url, item_url, updated_at, visibility }], page, per, total }
One item and its versions
GET https://getcadcraft.com/api/v1/library/items/{uuid}
→ data: { item: { …the list fields, description, author: { uuid, name },
versions: [{ version, status, change_kind, changelog, license, published_at,
item_url, preview_url, source_url|null, withdrawn_reason|null }] } }
GET https://getcadcraft.com/api/v1/library/items/{uuid}/{version}/item.json
→ 302 to the file; 451 when the version was withdrawn for copyright
Check for updates
POST https://getcadcraft.com/api/v1/library/updates
{ "items": [{ "uuid": "…", "version": 2 }] } (at most 500)
→ data: { results: [{ uuid, version, latest|null, status: "current" | "newer" | "withdrawn" | "unknown",
change_kinds: [], license_changed, withdrawn_reason|null }] }
Change kinds are geometry, data, license, fix. A copy someone already placed keeps the license it was placed under.
Signed-in apps
POST /api/v1/library/uses { uuid, version, app, file_label? }
DELETE /api/v1/library/uses?id=
GET /api/v1/library/notifications?unread=1
POST /api/v1/library/notifications/read { ids: [] } or { all: true }
POST /api/v1/library/follows { target_type: item|author|maker|category, target_key }
DELETE /api/v1/library/follows?id=
An app gets its key when you sign it in to the library from inside the app; you can revoke it on your account's security page.
Open feed
The feed is the open part: any library can serve it, and the apps can read any library that does ("Other feeds" in their library panel).
GET https://getcadcraft.com/api/v1/library/feed?since=<ISO 8601>&limit=
→ data: { events: [{ at, type: "item_published" | "version_published" | "version_withdrawn" | "license_changed",
uuid, version, item_url }], next_since }
Events are public items only, oldest first. Pass next_since back as since to continue; since is exclusive and a page never splits one second's events, so nothing is skipped.
To be an "other feed", serve /items, /items/{uuid}, /updates and /feed under one https base address with the shapes above, and allow cross-origin requests.