Fine-tuning datasets
A fine-tuning dataset turns rows of one of your assets into prompt/completion training pairs. You define the dataset against a connection and asset, generate it, then download the exports.
Generation reads sample rows through the asset's connection and writes several export files at once — OpenAI chat and completion JSONL, an Anthropic-style messages JSONL, and a generic CSV. Datasets, their rows, and their exports are private to you and keyed by an assetId from Discover assets on a connection.
- GET /v1/finetune/datasets List datasets
- POST /v1/finetune/datasets Create a dataset
- PUT /v1/finetune/datasets/{dataset_id} Update a dataset
- POST /v1/finetune/datasets/{dataset_id}/generate Generate a dataset
- GET /v1/finetune/datasets/{dataset_id}/exports List exports
- GET /v1/finetune/exports/{export_id}/download Download an export
Paths are relative to /data-api
The dataset object
A fine-tuning dataset definition and its generation state.
Attributes
-
idstringUnique identifier for the dataset.
-
namestringHuman-readable name.
-
connectionIdstringConnection the source asset belongs to.
-
assetIdstringAsset the training rows are drawn from.
-
mappingTemplatestringLabel recording the intended export shape (for example
openai-chat). Generation always produces every supported export format. -
statusstringGeneration state:
draft,generated, orfailed. -
rowCountintegerNumber of training rows produced by the last generation.
-
createdAtstringWhen the dataset was created.
-
updatedAtstringWhen the dataset was last updated.
{
"id": "9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"name": "Support replies",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d",
"mappingTemplate": "openai-chat",
"status": "generated",
"rowCount": 500,
"createdAt": "2026-09-01T11:00:00Z",
"updatedAt": "2026-09-01T11:02:00Z"
} List datasets
GET /data-api/v1/finetune/datasets
Returns your fine-tuning datasets, most recently updated first.
- Authentication
- Bearer token How it works
Parameters
No parameters.
Returns
Returns a list of dataset objects in data.
curl "$VDF_BASE_URL/data-api/v1/finetune/datasets" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/data-api/v1/finetune/datasets`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/data-api/v1/finetune/datasets",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"data": [
{
"id": "9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"name": "Support replies",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d",
"mappingTemplate": "openai-chat",
"status": "generated",
"rowCount": 500,
"createdAt": "2026-09-01T11:00:00Z",
"updatedAt": "2026-09-01T11:02:00Z"
}
]
} Create a dataset
POST /data-api/v1/finetune/datasets
Defines a fine-tuning dataset over a connection and asset.
Creates a dataset definition in draft status. It produces no training rows on its own; call Generate a dataset to build the rows and exports.
- Authentication
- Bearer token How it works
Body parameters application/json
-
namestring RequiredHuman-readable name.
-
connectionIdstring RequiredConnection the source asset belongs to.
-
assetIdstring RequiredAsset the training rows are drawn from.
-
mappingTemplatestring RequiredLabel recording the intended export shape, such as
openai-chat.
Returns
Returns the created dataset object in data.
Errors
- 400
name,connectionId,assetId, ormappingTemplateis missing. - 404 The connection or asset does not belong to you.
curl -X POST "$VDF_BASE_URL/data-api/v1/finetune/datasets" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Support replies",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d",
"mappingTemplate": "openai-chat"
}' const response = await fetch(`${process.env.VDF_BASE_URL}/data-api/v1/finetune/datasets`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Support replies',
connectionId: 'b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f',
assetId: '7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d',
mappingTemplate: 'openai-chat',
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/data-api/v1/finetune/datasets",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"name": "Support replies",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d",
"mappingTemplate": "openai-chat",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"data": {
"id": "9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"name": "Support replies",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d",
"mappingTemplate": "openai-chat",
"status": "draft",
"rowCount": 0,
"createdAt": "2026-09-01T11:00:00Z",
"updatedAt": "2026-09-01T11:00:00Z"
}
} Update a dataset
PUT /data-api/v1/finetune/datasets/{dataset_id}
Updates a dataset definition you own.
Updates the fields you supply. Changing the connection or asset does not regenerate rows; run Generate a dataset again to rebuild.
- Authentication
- Bearer token How it works
Path parameters
-
dataset_idstring RequiredIdentifier of the dataset to update.
Body parameters application/json
-
namestringNew name.
-
connectionIdstring RequiredConnection the source asset belongs to.
-
assetIdstring RequiredAsset the training rows are drawn from.
-
mappingTemplatestringNew export-shape label.
Returns
Returns the updated dataset object in data.
Errors
- 404 No dataset with this id belongs to you, or the target connection or asset does not belong to you.
curl -X PUT "$VDF_BASE_URL/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Support replies v2",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d"
}' const response = await fetch(`${process.env.VDF_BASE_URL}/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Support replies v2',
connectionId: 'b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f',
assetId: '7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d',
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.put(
f"{os.environ['VDF_BASE_URL']}/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"name": "Support replies v2",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"data": {
"id": "9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"name": "Support replies v2",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d",
"mappingTemplate": "openai-chat",
"status": "draft",
"rowCount": 0,
"createdAt": "2026-09-01T11:00:00Z",
"updatedAt": "2026-09-01T11:10:00Z"
}
} Generate a dataset
POST /data-api/v1/finetune/datasets/{dataset_id}/generate
Builds the training rows and export files for a dataset.
Reads sample rows from the asset through its connection, turns each into a prompt/completion pair, and writes the export files. Any previous rows and exports for the dataset are replaced. On success the dataset status becomes generated and rowCount reflects the rows produced; on failure it becomes failed. Download the results with Download an export.
- Authentication
- Bearer token How it works
Path parameters
-
dataset_idstring RequiredIdentifier of the dataset to generate.
Returns
Returns the dataset object with its updated status and row count in data.
Errors
- 404 No dataset with this id belongs to you, or its asset or connection no longer exists.
- 400 The asset returned no rows to build training data from.
- 502 The source could not be reached while reading rows.
- 500 Dataset generation failed.
curl -X POST "$VDF_BASE_URL/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d/generate" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d/generate`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d/generate",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"data": {
"id": "9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"name": "Support replies",
"connectionId": "b3f1c2e4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"assetId": "7a2d9e10-4c3b-4a1e-9f8d-2b6c1e0f5a3d",
"mappingTemplate": "openai-chat",
"status": "generated",
"rowCount": 500,
"createdAt": "2026-09-01T11:00:00Z",
"updatedAt": "2026-09-01T11:02:00Z"
}
} List exports
GET /data-api/v1/finetune/datasets/{dataset_id}/exports
Returns the export files generated for a dataset.
Returns the exports produced by the last generation of the dataset, newest first. Each export names its format and carries a downloadUrl for Download an export.
- Authentication
- Bearer token How it works
Path parameters
-
dataset_idstring RequiredIdentifier of the dataset whose exports to list.
Returns
Returns a list of export objects. Each has id, datasetId, format (one of openai-chat-jsonl, openai-completion-jsonl, anthropic-messages-jsonl, generic-csv), status, rowCount, downloadUrl, and createdAt in data.
Errors
- 404 No dataset with this id belongs to you.
curl "$VDF_BASE_URL/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d/exports" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d/exports`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/data-api/v1/finetune/datasets/9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d/exports",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"data": [
{
"id": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b",
"datasetId": "9d8c7b6a-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"format": "openai-chat-jsonl",
"status": "ready",
"rowCount": 500,
"downloadUrl": "/data-api/v1/finetune/exports/e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b/download",
"createdAt": "2026-09-01T11:02:00Z"
}
]
} Download an export
GET /data-api/v1/finetune/exports/{export_id}/download
Downloads a generated export file.
Streams the export file as an attachment. Only your own exports can be downloaded.
- Authentication
- Bearer token How it works
Path parameters
-
export_idstring RequiredIdentifier of the export to download.
Returns
Returns the export file as a download.
Errors
- 404 No export with this id belongs to you, or its file is no longer present.
curl "$VDF_BASE_URL/data-api/v1/finetune/exports/e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b/download" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-o download.bin const response = await fetch(`${process.env.VDF_BASE_URL}/data-api/v1/finetune/exports/e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b/download`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const file = await response.blob(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/data-api/v1/finetune/exports/e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b/download",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
stream=True,
timeout=30,
)
response.raise_for_status()
with open("download.bin", "wb") as output:
for chunk in response.iter_content(chunk_size=65536):
output.write(chunk)