● API reference

The D8alytics API.

Generate labeled datasets, track jobs, and pull results — straight from your own code.

Before you start

Four steps, about five minutes.

  1. Be on Pro or Enterprise. The API is not included in the Free plan — see plans.
  2. Create an API key in Dashboard → API keys and copy it. It is shown only once.
  3. Pick your system in the tabs on every example below — Windows, macOS / Linux, or Python. Choosing once sets it for the whole page.
  4. Run Check your key first. If that works, everything else will work too.

Overview

The API is a small REST interface over the same engine that powers the studios. All requests go to one base URL and return JSON.

Base URL
https://api.d8alytics.com/v1

The typical flow: create a dataset job, poll its status until it's completed, then request a download link for the resulting ZIP.

Authentication

Send your API key as a Bearer token on every request. Create and revoke keys in Dashboard → API keys. A key is shown only once when you create it, so store it safely. Keep keys server-side — never ship one in browser code.

Authorization: Bearer d8_live_xxxxxxxxxxxxxxxxxxxxxxxx

Quickstart

Generate a dataset end to end: start a job, wait for it, save the ZIP. Copy the whole block, put your key in, and run it.

$BASE = "https://api.d8alytics.com/v1"
$KEY  = "d8_live_YOUR_KEY"
$H    = @{ Authorization = "Bearer $KEY"; "Content-Type" = "application/json" }

# 1) start a job
$body = @{
  name = "PPE detection"
  parameters = @{
    prompt     = "workers on a construction site, CCTV angle"
    classes    = @("person","hard hat","safety vest")
    num_images = 6
  }
} | ConvertTo-Json -Depth 6

$job = Invoke-RestMethod -Uri "$BASE/jobs" -Headers $H -Method POST -Body $body
"Job started: $($job.job_id)"

# 2) wait until it is finished (checks every 15 seconds)
do {
  Start-Sleep -Seconds 15
  $s = Invoke-RestMethod -Uri "$BASE/jobs/$($job.job_id)" -Headers $H
  "$($s.status)  $($s.progress)%"
} while ($s.status -eq "pending" -or $s.status -eq "processing")

# 3) get the download link and save the ZIP
$dl = Invoke-RestMethod -Uri "$BASE/datasets/$($s.dataset_id)/download" -Headers $H
Invoke-WebRequest -Uri $dl.url -OutFile "dataset.zip"
BASE="https://api.d8alytics.com/v1"
KEY="d8_live_YOUR_KEY"
AUTH="Authorization: Bearer $KEY"

# 1) start a job                                    (needs curl and jq)
JOB=$(curl -s -X POST "$BASE/jobs" -H "$AUTH" -H "Content-Type: application/json" \
  -d '{"name":"PPE detection","parameters":{
        "prompt":"workers on a construction site, CCTV angle",
        "classes":["person","hard hat","safety vest"],
        "num_images":6}}' | jq -r .job_id)
echo "Job started: $JOB"

# 2) wait until it is finished (checks every 15 seconds)
while true; do
  S=$(curl -s "$BASE/jobs/$JOB" -H "$AUTH")
  echo "$(echo "$S" | jq -r .status)  $(echo "$S" | jq -r .progress)%"
  case "$(echo "$S" | jq -r .status)" in completed|failed|cancelled) break;; esac
  sleep 15
done

# 3) get the download link and save the ZIP
DS=$(echo "$S" | jq -r .dataset_id)
URL=$(curl -s "$BASE/datasets/$DS/download" -H "$AUTH" | jq -r .url)
curl -sL "$URL" -o dataset.zip
# pip install requests
import time, requests

BASE = "https://api.d8alytics.com/v1"
KEY  = "d8_live_YOUR_KEY"
H    = {"Authorization": f"Bearer {KEY}"}

# 1) start a job
job = requests.post(f"{BASE}/jobs", headers=H, json={
    "name": "PPE detection",
    "parameters": {
        "prompt": "workers on a construction site, CCTV angle",
        "classes": ["person", "hard hat", "safety vest"],
        "num_images": 6,
    },
}).json()
print("Job started:", job["job_id"])

# 2) wait until it is finished (checks every 15 seconds)
while True:
    s = requests.get(f"{BASE}/jobs/{job['job_id']}", headers=H).json()
    print(s["status"], s["progress"], "%")
    if s["status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(15)

# 3) get the download link and save the ZIP
url = requests.get(f"{BASE}/datasets/{s['dataset_id']}/download", headers=H).json()["url"]
with open("dataset.zip", "wb") as f:
    f.write(requests.get(url).content)

Generation takes a few minutes — that is the GPU doing real work, not a problem. The ZIP is ready to train on: images/, labels/, data.yaml.

Check your key

GET /me

Confirms a key works and shows the limits on your plan. Good first call.

Invoke-RestMethod -Uri "https://api.d8alytics.com/v1/me" `
  -Headers @{ Authorization = "Bearer YOUR_API_KEY" }
curl https://api.d8alytics.com/v1/me \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

r = requests.get("https://api.d8alytics.com/v1/me",
                 headers={"Authorization": "Bearer YOUR_API_KEY"})
print(r.json())
200 OK
{
  "user_id": "cbcd9721-bbc3-4a0e-b3e9-8bf92110421d",
  "email": "[email protected]",
  "plan": "pro",
  "limits": {
    "requests_per_minute": 60,
    "dataset_jobs_per_day": 50,
    "max_images_per_job": 15,
    "max_classes_per_job": 6
  }
}

Create a dataset job

POST /jobs

Starts a generation job. Returns a job_id you can poll. Jobs run in the same queue as the studios.

$body = @{
  name = "PPE detection"
  parameters = @{
    prompt         = "workers on a construction site, CCTV angle"
    classes        = @("person","hard hat","safety vest")
    label_guide    = "hard hat: box only the helmet, not the head."
    num_images     = 6
    image_size     = 1024
    augment_copies = 0
  }
} | ConvertTo-Json -Depth 6

Invoke-RestMethod -Uri "https://api.d8alytics.com/v1/jobs" -Method POST -Body $body `
  -Headers @{ Authorization = "Bearer YOUR_API_KEY"; "Content-Type" = "application/json" }
curl -X POST https://api.d8alytics.com/v1/jobs \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "PPE detection",
    "parameters": {
      "prompt": "workers on a construction site, CCTV angle",
      "classes": ["person", "hard hat", "safety vest"],
      "label_guide": "hard hat: box only the helmet, not the head.",
      "num_images": 6,
      "image_size": 1024,
      "augment_copies": 0
    }
  }'
import requests

r = requests.post("https://api.d8alytics.com/v1/jobs",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "name": "PPE detection",
        "parameters": {
            "prompt": "workers on a construction site, CCTV angle",
            "classes": ["person", "hard hat", "safety vest"],
            "label_guide": "hard hat: box only the helmet, not the head.",
            "num_images": 6,
            "image_size": 1024,
            "augment_copies": 0,
        },
    })
print(r.json())
201 Created
{
  "job_id": "9b0e46c1-417f-4320-99a7-b2b0c4c7cc00",
  "status": "pending",
  "created_at": "2026-07-27T10:12:04.518Z"
}

Get job status

GET /jobs/:id

Poll until status is completed (or failed / cancelled). Polling every 10–15 seconds is plenty.

Invoke-RestMethod -Uri "https://api.d8alytics.com/v1/jobs/JOB_ID" `
  -Headers @{ Authorization = "Bearer YOUR_API_KEY" }
curl https://api.d8alytics.com/v1/jobs/JOB_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

r = requests.get("https://api.d8alytics.com/v1/jobs/JOB_ID",
                 headers={"Authorization": "Bearer YOUR_API_KEY"})
print(r.json())
200 OK
{
  "job_id": "9b0e46c1-417f-4320-99a7-b2b0c4c7cc00",
  "type": "dataset",
  "status": "completed",
  "stage": "completed",
  "progress": 100,
  "created_at": "2026-07-27T10:12:04.518Z",
  "started_at": "2026-07-27T10:12:19.002Z",
  "completed_at": "2026-07-27T10:18:41.774Z",
  "dataset_id": "b2f1c0de-8a44-4f2e-9d31-6f0b7a2c1e55",
  "total_images": 6,
  "total_objects": 41,
  "size_bytes": 5241880,
  "error": null
}

status is one of pending, processing, completed, failed, cancelled. While a job runs, stage and progress show how far along it is; dataset_id stays null until it finishes.

Download a dataset

GET /datasets/:id/download

Returns a short-lived signed URL to the dataset ZIP (YOLO format: images/, labels/, data.yaml, plus metadata). Follow the URL to fetch the file.

$dl = Invoke-RestMethod -Uri "https://api.d8alytics.com/v1/datasets/DATASET_ID/download" `
  -Headers @{ Authorization = "Bearer YOUR_API_KEY" }

# then save the file
Invoke-WebRequest -Uri $dl.url -OutFile "dataset.zip"
URL=$(curl -s https://api.d8alytics.com/v1/datasets/DATASET_ID/download \
  -H "Authorization: Bearer YOUR_API_KEY" | jq -r .url)

# then save the file
curl -sL "$URL" -o dataset.zip
import requests

url = requests.get("https://api.d8alytics.com/v1/datasets/DATASET_ID/download",
                   headers={"Authorization": "Bearer YOUR_API_KEY"}).json()["url"]

# then save the file
with open("dataset.zip", "wb") as f:
    f.write(requests.get(url).content)
200 OK
{ "url": "https://cdn-lfs.huggingface.co/...signed...", "expires_in": 300 }

The link expires in about 5 minutes — request a new one whenever you need it. If the dataset isn't finished yet you get 409 not_ready.

Parameters

All generation options go inside parameters. Only prompt and classes are required.

FieldTypeNotes
promptstringRequired. What the images should show.
classesstring[]Required. Objects to detect, one label each. Max 6.
label_guidestringPer-class definitions. Strongly recommended for accurate labels.
num_imagesintImages to generate. Default 5, max 15.
image_sizeint640 or 1024. Default 1024.
environmentsstring[]Optional. Rotated across images for variety.
capturesstring[]Optional. Capture/realism variety.
augment_copiesintExtra augmented variants per image (0–10). Default 0.

Errors & limits

Every error returns the same shape, with a matching HTTP status:

{ "error": { "code": "limit_exceeded", "message": "Too many images: 40. Your plan allows 15 per job." } }
StatusCodeMeaning
400invalid_requestA required field is missing or malformed.
400limit_exceededMore images or classes than your plan allows.
401unauthorizedKey missing, wrong, or revoked.
403forbiddenPlan without API access, or the resource is another account's.
404not_foundUnknown job, dataset, or endpoint.
409not_readyThe dataset hasn't finished generating yet.
429rate_limitedToo many requests per minute, or the daily job quota is used up.

Rate limits

PlanRequests / minDataset jobs / dayImages / jobClasses / job
Pro6050156
Enterprise300500156

Need higher image or class limits for a large workload? Talk to us — these are tied to dedicated generation capacity.

Create an API key See plans