---
title: "Fit an accessory to a rigged 3D model for Directional Sprites: an item GLB (a sword, a gun, a staff, a bow, a shield, a helmet, a hat, a backpack...) held by one bone of the model - a hand, the head, the back or the hips. Nothing is saved. The item is first placed automatically for its `kind` (a sword by its handle, a gun by its pistol grip, a shield on the forearm, a helmet over the head, a backpack on the back), and the hand closes round it. Adjust it relative to that automatic fit with `size` (% of it), `move` (% of the character's height along forward/up/out) and `turn` (degrees about those axes), and call again with the new values until it looks right: each call starts from the automatic fit, so send the full adjustment every time. The response has the `placement` to pass to attachDirectionalAccessories, `checks` (how far the item sinks into the body, how far its grip is from the palm, how much of the head pokes through a helmet, each in % of the character's height or of its vertices), and, unless `preview` is false, `model_url` (the model holding the item, a GLB kept 7 days) and `previews`: frames of the model walking with it, seen from SW and SE, like previewDirectionalSprites' (which this shares: one preview at a time, a newer one cancels the older, which then comes back without previews). Free (no credits) and synchronous; a fit takes a few seconds with previews. Requires an API key (user scope)."
method: POST
path: "/assets/sprite/directional-accessory-fit"
tags: ["Spritesheets"]
---

# Fit an accessory to a rigged 3D model for Directional Sprites: an item GLB (a sword, a gun, a staff, a bow, a shield, a helmet, a hat, a backpack...) held by one bone of the model - a hand, the head, the back or the hips. Nothing is saved. The item is first placed automatically for its \`kind\` (a sword by its handle, a gun by its pistol grip, a shield on the forearm, a helmet over the head, a backpack on the back), and the hand closes round it. Adjust it relative to that automatic fit with \`size\` (% of it), \`move\` (% of the character's height along forward/up/out) and \`turn\` (degrees about those axes), and call again with the new values until it looks right: each call starts from the automatic fit, so send the full adjustment every time. The response has the \`placement\` to pass to attachDirectionalAccessories, \`checks\` (how far the item sinks into the body, how far its grip is from the palm, how much of the head pokes through a helmet, each in % of the character's height or of its vertices), and, unless \`preview\` is false, \`model_url\` (the model holding the item, a GLB kept 7 days) and \`previews\`: frames of the model walking with it, seen from SW and SE, like previewDirectionalSprites' (which this shares: one preview at a time, a newer one cancels the older, which then comes back without previews). Free (no credits) and synchronous; a fit takes a few seconds with previews. Requires an API key (user scope).

`POST /assets/sprite/directional-accessory-fit`

## Request

- Base URL: `https://api.ludo.ai/api`
- URL: `https://api.ludo.ai/api/assets/sprite/directional-accessory-fit`
- Auth: API key in header `Authorization`
- TypeScript: <https://skmtc.dev/ludo/apis/ludo-ai-api/docs/assets/sprite/directional-accessory-fit/post.ts> (a function with typed inputs; its response is checked against the schema)

## Request body

- DirectionalAccessoryFitPayload: Payload for fitting an accessory to a rigged 3D model
  - `model` string, required: The rigged 3D model, as a URL or base64-encoded GLB file - create3DModel with rig true, or rigModel. Up to 30MB; a larger file is rejected with HTTP 400.
  - `item` string, required: The item, as a URL or base64-encoded GLB file - any 3D model (create3DModel without rig, standing as generated). Up to 30MB.
  - `name` string: What the item is, in words ("rusty sword"). Used to guess `kind` when it is omitted, and as the item's name when saved.
  - `kind` 'blade' | 'gun' | 'staff' | 'bow' | 'shield' | 'helmet' | 'hat' | 'back' | 'other': What the item is, which decides how it is first held: blade (sword, axe, dagger, mace, wand...: by its handle, pointing forward), gun (by its pistol grip, barrel forward), staff (spear, polearm: at its middle, upright), bow (at its middle, upright), shield (on the forearm, facing out), helmet (over the head, sized to it), hat (hat or crown: on top of the head), back (backpack, quiver: flat on the back), other. Omit to guess it from `name` and the item's shape (other when unsure).
  - `point` 'right_hand' | 'left_hand' | 'head' | 'back' | 'hips': Where the item goes. Omit for where its kind goes (a bow and a shield in the left hand, a helmet or hat on the head, a backpack on the back, anything else in the right hand). The response lists the points this skeleton has.
  - `bone` string: A bone of the model's skeleton to hold the item, by name, instead of `point`.
  - `size` number, float: The item's size in % of the automatic fit's (100 = as fitted, 150 = half as big again).
  - `move` DirectionalAccessoryAxes: Along or about the character's own axes: forward (where it faces), up, and out (away from the body's middle for an item in a hand; to the character's left on the head, back or hips).
    - `forward` number, float
    - `up` number, float
    - `out` number, float
  - `turn` DirectionalAccessoryAxes: Along or about the character's own axes: forward (where it faces), up, and out (away from the body's middle for an item in a hand; to the character's left on the head, back or hips).
    - `forward` number, float
    - `up` number, float
    - `out` number, float
  - `flip` boolean: Hold the item by its other end (when the automatic fit grabbed it by the wrong end).
  - `grip` boolean: Close the hand round the item (on a skeleton with finger bones).
  - `preview` boolean: Render previews and host the model holding the item. False answers only the fit and its checks, in about a second.
  - `preview_preset_id` string: The animation preset (listAnimationPresets) the previews show the model doing with the item.

## Response `200`

Success

- DirectionalAccessoryFitResult
  - `kind` string: What the item was fitted as (as sent, or guessed).
  - `point` string: The attach point the bone is, if it is one.
  - `bone` string: The bone holding the item.
  - `size` number, float
  - `move` DirectionalAccessoryAxes: Along or about the character's own axes: forward (where it faces), up, and out (away from the body's middle for an item in a hand; to the character's left on the head, back or hips).
    - `forward` number, float
    - `up` number, float
    - `out` number, float
  - `turn` DirectionalAccessoryAxes: Along or about the character's own axes: forward (where it faces), up, and out (away from the body's middle for an item in a hand; to the character's left on the head, back or hips).
    - `forward` number, float
    - `up` number, float
    - `out` number, float
  - `flip` boolean
  - `grip` boolean
  - `placement` DirectionalAccessoryPlacement: Where an item is held, exactly. Pass it unchanged to attachDirectionalAccessories.
    - `bone` string
    - `point` string
    - `kind` string
    - `flipped` boolean
    - `grip` boolean
    - `base_scale` number, float: The automatic fit's scale (size 100).
    - `position` number[]
    - `quaternion` number[]
    - `scale` number[]
  - `checks` DirectionalAccessoryChecks: Numbers about the fit, from sampled vertices in the model's rest pose: a quick way to tell a fine fit from a clearly wrong one.
    - `sink` number, float: How deep the item goes into the body, in % of the character's height (95th percentile of its vertices). Near 0 is right; an item in a hand is checked against the body without that hand.
    - `inside` number, float: The share of the item's vertices under the body's surface, in %.
    - `grip_gap` number, float: For an item held by a grip in a hand (not a shield) - how far its grip is from the palm, in % of the character's height. Near 0 is in the fist.
    - `through` number, float: For an item on the head - the share of the head's vertices (hair and all) poking out through it, in %: for a helmet, where it covers the head; for a hat, under the hat only (ears standing beside it are not counted). A helmet draws in what would poke through it (hair, ear tips) when it is put on, so near 0 is expected.
  - `points` object[]: The attach points this model's skeleton has, with the bone each one is.
    - `point` string
    - `bone` string
  - `model_url` string: The model holding the item, as a GLB (kept 7 days). Unless preview is false.
  - `previews` DirectionalPreview[]: The model holding the item, doing the preview animation, from SW and SE (isometric); 4 frames each. Unless preview is false.
    - `direction` string: The direction this preview is seen from.
    - `frame_urls` string[]: The preview's frames as images, in order (one for a still model). Kept for 7 days.
    - `width` integer
    - `height` integer
    - `num_frames` integer
    - `fps` number, float
    - `render_3d` DirectionalSpriteRender
      - `style_id` string
      - `style_version` integer
      - `style_params` object: The style's settings as rendered, by name.
      - `perspective` string
      - `direction` string
      - `animation_name` string
      - `fps` number, float
      - `keep_horizontal_travel` boolean
      - `keep_vertical_travel` boolean
  - `preview_error` string: Why there are no previews, when they could not be made (the fit itself is still valid).

## Other responses

- `400`: Error
- `503`: Fitting temporarily busy, retry in a few seconds

## Changes

- **2026-11-04** `7921d7892dbf`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/ludo/apis/ludo-ai-api/changes/assets/sprite/directional-accessory-fit/post.md)

---

[API](https://skmtc.dev/ludo/apis/ludo-ai-api.md) - [All operations](https://skmtc.dev/ludo/apis/ludo-ai-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ludo/apis/ludo-ai-api/revisions/970a84f6c315?raw)
