Skip to main content

HTTP API reference

Base URL: https://api.moondream.ai/v1/tuning/

Authentication

All requests require the X-Moondream-Auth header with your API key:

X-Moondream-Auth: YOUR_API_KEY

Get your API key from the Moondream Cloud Console.


POST /finetunes

Create a new finetune.

Request

{
"name": "my-finetune",
"rank": 32
}
FieldTypeRequiredDescription
namestringyesUnique name for this finetune (alphanumeric, hyphens, underscores)
rankintegeryesLoRA rank: 8, 16, 24, or 32 (must be multiple of 8; higher = more capacity, but slower)

Response

{
"finetune_id": "01HXYZ..."
}
FieldTypeDescription
finetune_idstringUnique identifier (ULID) for the finetune. Use this ID for all subsequent operations.

If a finetune with the same name already exists with the same rank, the existing finetune_id is returned (idempotent). If the name exists with a different rank, returns 409 Conflict.


GET /finetunes

List all finetunes for your organization.

Query parameters

ParameterTypeDefaultDescription
limitinteger50Maximum results per page (1–100)
cursorstringPagination cursor from previous response

Response

{
"finetunes": [
{
"finetune_id": "01HXYZ...",
"name": "my-finetune",
"rank": 32,
"created_at_ms": 1736937000000,
"updated_at_ms": 1736937000000
}
],
"next_cursor": "eyJjIjoiMjAyNS0wMS0xNVQxMDozMDowMFoifQ==",
"has_more": true
}

Results are ordered by creation time (oldest first).


GET /finetunes/:finetuneId

Get details for a specific finetune.

Response

{
"finetune_id": "01HXYZ...",
"name": "my-finetune",
"rank": 32,
"created_at_ms": 1736937000000,
"updated_at_ms": 1736937000000
}

Returns 404 if the finetune does not exist.


DELETE /finetunes/:finetuneId

Delete a finetune. This is a soft delete—the finetune is marked as deleted and its checkpoints are cleaned up asynchronously.

Response

Returns { "ok": true } on success.

Constraints:

  • Returns 404 if the finetune does not exist.

POST /rollouts

Generate rollouts for a training or evaluation request.

Request

{
"finetune_id": "01HXYZ...",
"num_rollouts": 4,
"request": { ... },
"ground_truth": { ... } // optional
}
FieldTypeRequiredDescription
finetune_idstringyesThe finetune ID (from POST /finetunes response)
num_rolloutsintegeryesNumber of attempts to generate (1–16)
requestobjectyesSkill-specific request (see below)
ground_truthobjectnoGround truth for automatic reward computation (point/detect only)

Skill requests

Query

{
"skill": "query",
"question": "What color is the car?",
"image_url": "data:image/jpeg;base64,...", // optional
"reasoning": false, // optional
"settings": {
"temperature": 1.0,
"top_p": 1.0,
"max_tokens": 128
}
}
FieldTypeRequiredDescription
skillstringyesMust be "query"
questionstringyesThe question to answer
image_urlstringnoBase64 data URL of the image
reasoningbooleannoEnable extended reasoning (default: false)
settingsobjectnoGeneration settings

Point

{
"skill": "point",
"object": "the red button",
"image_url": "data:image/jpeg;base64,...",
"settings": {
"temperature": 1.0,
"top_p": 1.0,
"max_tokens": 128
}
}
FieldTypeRequiredDescription
skillstringyesMust be "point"
objectstringyesDescription of the object to point to
image_urlstringyesBase64 data URL of the image
settingsobjectnoGeneration settings

Detect

{
"skill": "detect",
"object": "vehicles",
"image_url": "data:image/jpeg;base64,...",
"settings": {
"temperature": 1.0,
"top_p": 1.0,
"max_tokens": 256,
"max_objects": 8
}
}
FieldTypeRequiredDescription
skillstringyesMust be "detect"
objectstringyesDescription of objects to detect
image_urlstringyesBase64 data URL of the image
settingsobjectnoGeneration settings (includes max_objects)

Settings

FieldTypeDefaultDescription
temperaturenumber1.0Controls randomness (0 = deterministic)
top_pnumber1.0Nucleus sampling threshold
max_tokensinteger128Maximum output length
max_objectsintegerMaximum objects to detect (detect only)

Ground truth

Point — coordinates:

{
"points": [{ "x": 0.52, "y": 0.31 }]
}

Point — bounding boxes (rewards based on containment):

{
"boxes": [{ "x_min": 0.1, "y_min": 0.2, "x_max": 0.4, "y_max": 0.6 }]
}

Detect:

{
"boxes": [
{ "x_min": 0.1, "y_min": 0.2, "x_max": 0.4, "y_max": 0.6 }
]
}

All coordinates are normalized to 0–1.

Response

{
"request": { ... },
"rollouts": [
{
"skill": "detect",
"output": {
"objects": [
{ "x_min": 0.12, "y_min": 0.22, "x_max": 0.39, "y_max": 0.58 }
]
},
// ... opaque training metadata
}
],
"rewards": [0.8, 0.3, 0.6, 0.5]
}
FieldTypeDescription
requestobjectEchoed request
rolloutsarrayGenerated rollouts
rewardsarray | nullComputed rewards if ground truth was provided

Rollout output by skill

Query:

{
"answer": "The car is red.",
"reasoning": null // present if reasoning was enabled
}

Point:

{
"points": [{ "x": 0.52, "y": 0.31 }]
}

Detect:

{
"objects": [
{ "x_min": 0.12, "y_min": 0.22, "x_max": 0.39, "y_max": 0.58 }
]
}

POST /train_step

Apply one training step using scored rollouts.

Request

{
"finetune_id": "01HXYZ...",
"groups": [
{
"request": { ... },
"rollouts": [ ... ],
"rewards": [0.8, 0.3, 0.6, 0.5]
}
],
"lr": 0.002
}
FieldTypeRequiredDescription
finetune_idstringyesThe finetune ID to train
groupsarrayyesList of training groups
lrnumbernoLearning rate (default: 0.002)

Each group:

FieldTypeRequiredDescription
requestobjectyesThe echoed request from /rollouts response
rolloutsarrayyesThe rollout objects from /rollouts response (pass unchanged)
rewardsarrayyesReward for each rollout (same length and order)

You can mix skills across groups in the same train step.

Response

{}

GET /finetunes/:finetuneId/checkpoints

List saved checkpoints for a finetune.

Query parameters

ParameterTypeDefaultDescription
limitinteger50Maximum results per page (1–100)
cursorstringPagination cursor from previous response

Response

{
"checkpoints": [
{
"checkpoint_id": "01JXYZ...",
"finetune_id": "01HXYZ...",
"step": 100,
"created_at_ms": 1736937000000,
"updated_at_ms": 1736937600000
}
],
"next_cursor": "eyJzIjo1MDB9",
"has_more": true
}
FieldTypeDescription
checkpoint_idstringUnique checkpoint identifier
finetune_idstringFinetune identifier
stepintegerTraining step number
created_at_msintegerUnix timestamp in milliseconds
updated_at_msintegerUnix timestamp in milliseconds

Results are ordered by step (ascending). Only saved checkpoints are returned.


POST /finetunes/:finetuneId/checkpoints/save

Save the current checkpoint and make it visible in the dashboard. The server resolves the current step for the finetune.

Response

{
"ok": true,
"checkpoint": {
"checkpoint_id": "01JXYZ...",
"finetune_id": "01HXYZ...",
"step": 100,
"created_at_ms": 1736937000000,
"updated_at_ms": 1736937600000
}
}

Constraints:

  • Returns 404 if the finetune does not exist or no checkpoint is available.
  • Idempotent: repeated calls return success.

DELETE /finetunes/:finetuneId/checkpoints/:step

Delete a saved checkpoint. The checkpoint will be cleaned up shortly.

Response

{ "ok": true }

Constraints:

  • Returns 404 if the checkpoint does not exist.
  • Returns 410 if the checkpoint was already deleted.

Deleting the latest checkpoint will prevent resuming training for that finetune.


Using finetuned models for inference

Once you have saved a checkpoint, you can use it for inference by specifying the model parameter in your API requests.

Model format

moondream3-preview/{finetune_id}@{step}

For example, if your finetune ID is 01HXYZ... and you saved a checkpoint at step 500:

moondream3-preview/01HXYZ...@500

Example: Query with a finetuned model

curl -X POST https://api.moondream.ai/v1/query \
-H "X-Moondream-Auth: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "moondream3-preview/01HXYZ...@500",
"image_url": "data:image/jpeg;base64,...",
"question": "What do you see?"
}'

Supported endpoints

The model parameter is supported on the following inference endpoints:

EndpointDescription
/v1/queryQuestion answering
/v1/captionImage captioning
/v1/detectObject detection
/v1/pointPoint localization
/v1/batchBatch processing (model specified at upload completion)

Notes

  • The model parameter is optional. If omitted, requests use the base moondream3-preview model.
  • Only saved checkpoints can be used for inference. Use POST /finetunes/:finetuneId/checkpoints/save to save a checkpoint first.
  • Both the finetune_id and step are required in the model string.
  • Finetune inference is only available for authenticated API requests (not available in playground mode).