{
    "name": "Polyfork API",
    "read_this_first": "https://polyfork.dev/prompt.txt",
    "read_this_first_note": "the catalogue as working instructions: how to pick assets that go together, assemble a kit on its grid, animate what is riggable, and what a key does and does not unlock. One fetch, no SDK.",
    "docs": "https://polyfork.dev/llms.txt",
    "auth": "Authorization: Bearer <key>; create keys at https://polyfork.dev/account",
    "endpoints": {
        "GET /api/assets": "browse published assets; filters: q, class (prop|building|vehicle|character|animal|ultra|attachment|terrain|hand), free (0|1), kit, ik (1|legs|arm: models that SOLVE rather than pose), max_triangles, min_triangles, sort (latest|tris|price), page, per_page (max 100), fields=compact for shortlisting rows. q is word-matched and scored: `coverage` says whether anything actually answers it and `strong_matches` counts the rows that do. max_price_usd is deprecated: assets are free or included in Pro, so use free=1",
        "GET /api/assets/{id}": "one asset with full metadata and download URLs",
        "GET /api/assets/{id}/matching": "assets that go WITH this one: same kit, then shared palette, then compatible scale",
        "GET /api/assets/{id}/variant?want=...": "plain words to a ready createAsset() call, plus a glb URL and a glb_note saying whether that file actually shows the variant",
        "GET /api/kits": "kits with their published part counts and a status: \"published\" (finished, sold as a bundle) or \"filling-up\" (still being built, parts usable today, no bundle price yet)",
        "GET /api/kits/{id}": "one kit with its published parts \u2014 including a kit that is still filling up. Also `look` (the shader the kit is presented under, shipped in its download) and `terrain` (its own ground program and the knobs it was composed at) where it has them: a scene built without those is the same parts on a flat floor",
        "GET /api/terrain": "kits that ship a procedural terrain program for their own ground",
        "GET /api/terrain/{id}": "answers are in the coordinates of the mesh createAsset() builds, so they can be used as they are; ?edges=tile for the tiled build instead, and origin_offset says what separates the two. AT WHAT HEIGHT DO I PLACE THIS: ?at=x,z;x,z returns the ground height and slope under each point \u2014 set position.y to it and the object rests on the terrain. flat_areas are level building sites, largest first, each with its own y. ?scatter=n gives n placement points already on the ground for rocks and trees. ?profile=x0,z0,x1,z1 gives the ground along a road or wall (heights, grade, where it is under water). ?span=1..4 sizes the block, ?flatten=0..1 clears a level area in the middle for a settlement. World coordinates throughout",
        "GET /api/me": "the key's account: email, plan, owned items. Works WITHOUT a key too, returning your anonymous tier and remaining bake quota, so a client can warn before a limit",
        "POST /api/demand": "report something a user wanted that we do not have: {\"need\": \"...\", \"email\": \"...\"}"
    },
    "conventions": {
        "up_axis": "y",
        "units": "meters, real-world scale (a barrel is about 0.9m, a car about 4.2m)",
        "origin": "the model rests ON y=0 (minY is 0) and is centred on x and z, so placing it is setting position to the ground point \u2014 no bounding-box maths, no sinking. TWO EXCEPTIONS, both built that way on purpose and both flagged: assets fixed to a wall or ceiling are built at installed height (a fire-exit sign at y=2.2), and ground tiles and terrains sit BELOW the origin so their top surface lands on y=0. Every list row carries origin_y \u2014 the measured minY, 0 for the rule and non-zero for an exception \u2014 and the detail row carries `origin` as a sentence. In all three cases you still place at y=0 and never lift by the bounding box; the number is there so you can tell what standing something ON it means",
        "facing": "the front of the object faces +Z",
        "handedness": "right-handed, three.js convention; GLB and FBX exports keep it",
        "materials": "flat-shaded vertex colours in the module; exports bake the palette into NAMED materials, named after the asset's own colour knobs, so a model never arrives white",
        "determinism": "same knob values always produce the same geometry; no Math.random anywhere",
        "formats": [
            "mjs",
            "glb",
            "fbx",
            "usdz",
            "obj"
        ],
        "animation": "assets that move ship a looping clip inside the GLB and FBX; USDZ and OBJ carry the mesh only, so every asset also reads correctly as a single still frame",
        "react_three_fiber": "R3F takes any Object3D through <primitive>, and createAsset() returns a ready THREE.Group synchronously, so there is no loader, useGLTF or Suspense. Knobs become props: const obj = useMemo(() => createAsset(props), [JSON.stringify(props)]); return <primitive object={obj} />. Import the .mjs as a local file, not a https:// URL, because bundlers do not resolve remote imports. Guide: https://polyfork.dev/react-three-fiber",
        "kit_coherence": "parts of one kit share a palette, a scale and a grid module, so they can be placed together without a coherence pass",
        "licence": "commercial use, modification, no attribution. Do not resell or redistribute the assets themselves as assets, or use them to build or train a COMMERCIAL asset generator: a model, service or pipeline that produces 3D assets and that you sell or offer to others. Personal experiments, research and learning are fine. Breaking these terms can end your licence and your access, without a refund."
    },
    "every asset carries": "has_rig (animatable parts), remixable (createAsset knobs), has_night (lights up after dark), has_ik (boolean) and ik_type (\"legs\", \"arm\" or null: the model is solvable, so its feet can find your ground or its tip can be aimed. The measured gait/arm block is on the detail endpoint; the runtime is https://polyfork.dev/cdn/walk.mjs)",
    "the ground": "natural ground is not modelled as parts; every kit generates it. Ask /api/terrain for level sites before inventing coordinates for a town, and stay seam_margin_m clear of the bounds or you are building across a join between two kits",
    "scenes": "https://polyfork.dev/scene?ids=a,b,c renders a composed scene as a shareable page",
    "downloads": "free assets: public CDN URLs, no auth. paid assets you own: /dl URLs with the same Bearer key.",
    "if the asset does not exist": "https://polyfork.dev/steer puts a 60-part kit of your own theme on the production line, from $85. A planner writes the parts list and draws 3 concept looks before you pay.",
    "if your product will serve these to ITS users": "that is redistribution and no plan covers it, but it is for sale rather than forbidden: https://polyfork.dev/platform, from $299/month. Say so before building the integration.",
    "why authenticate": {
        "as": "anonymous",
        "remix_bakes_per_hour": 40,
        "remix_bakes_left_this_hour": 40,
        "remix_note": "The budget is on generating NEW geometry. Variations anyone has already baked are served to everybody and never counted, so re-fetching a variant you or anyone else has made costs nothing.",
        "remix_bakes_per_month": 100,
        "remix_bakes_left_this_month": 100,
        "remix_allowance_resets": "2026-10-01",
        "remix_allowance_note": "A free account raises this to 300 a WEEK, and costs an email address.",
        "a_free_account_adds": {
            "how": "Authorization: Bearer <key>, created at https://polyfork.dev/account. Costs an email address.",
            "remix_bakes_per_hour": 100,
            "remix_bakes_per_week": 300,
            "downloads": "every FREE asset as .glb, .mjs and a ready-to-serve zip"
        },
        "pro_adds": {
            "url": "https://polyfork.dev/pricing",
            "usd_per_year": 149,
            "module_mjs": "the createAsset() program itself \u2014 knobs evaluated in YOUR engine at runtime, no bake, no round trip, no per-variant file",
            "structured_glb": "the authored GLB: named parts, detachables, real material names, real normals. Worth most where the public preview is one joined anonymous mesh \u2014 every static asset and 186 of the 499 rigged ones. The other 313 rigged assets keep their hierarchy in the preview and can demo themselves without this; get_asset's preview_rig says which you have",
            "cdn": "a per-account /c/<token>/ path you can hotlink from a shipped build; it keeps up when an asset is rebuilt, and the token is not the API key",
            "remix_bakes_per_hour": 900,
            "remix_bakes_per_week": "uncapped \u2014 a free account gets a weekly allowance, Pro does not"
        }
    }
}
