← Home

API Reference

Every trained model ships as a secured REST endpoint. Call it from any language or framework — no SDK required.

Base URL

https://cletus-service.onrender.com

All endpoints are HTTPS. The API host can sleep when idle, so the first request after a quiet period may take up to 30s.

Authentication

Prediction endpoints

Send X-API-Key: <your_api_key>. Each model has its own key (shown on the model page, rotate it any time); a key only works for its own model.

Dashboard endpoints

Send Authorization: Bearer <access_token>, the session token from signing in.

POST /predict/{job_id}

Run one prediction. This is the endpoint your application calls.

Request body

{
  "inputs": {
    "age": 42,
    "city": "boston",
    "income": 61000
  }
}

Keys are your training file's column names (minus the target and any dropped columns). Send the raw values as they appeared in the file: numbers as numbers (numeric strings are fine), categories as the original text. Leave out anything you don't know — it's filled in and reported in warnings.

Response — 200 OK

{
  "prediction": "yes",          // number for regression, class label for classification
  "confidence": 0.83,           // 0–1 (null if unavailable)
  "job_id": "xxxxxxxx-...",
  "model_name": "Churn model",
  "all_probabilities": {        // multiclass models only
    "yes": 0.83, "no": 0.17
  },
  "warnings": [                 // only when inputs were filled in or ignored
    "'income' was missing; used the training median (58200)."
  ]
}

For regression, confidence is a heuristic based on how far the prediction is from the training mean, not a statistical interval.

Errors

StatusMeaning
400Model not ready, or an input has the wrong type (e.g. text for a numeric column)
401Missing or invalid X-API-Key
403The key belongs to a different model
413Request body too large (15 MB for /predict, 1 MB for most other endpoints)
422Malformed body (e.g. inputs is not an object, more than 1,000 batch rows)
429Rate limit or monthly prediction quota reached — see Rate limits & quotas
500Server error (e.g. model files missing)

Every error body is { "error": "description" }.

Image models

Train by uploading a .zip with one folder per class (cats/001.jpg, dogs/002.png; 2–100 classes, at least 2 images each, up to 3,000 images). Each image is resized and center-cropped to 224×224 and passed through a pretrained MobileNetV3 network; a small classifier is trained on its features. Predict by sending the image base64-encoded:

{ "inputs": { "image": "<base64 image, or a data:image/...;base64,... URL>" } }

JPG, PNG, WebP, BMP, or GIF, up to 10 MB decoded. The response has the same shape as above, with all_probabilities for every class.

POST /predict/{job_id}/batch

Up to 1,000 rows in one request, same X-API-Key. Each row counts toward the monthly quota.

// request
{ "rows": [ { "age": 42, "city": "boston" }, { "age": 23, "city": "austin", "income": 30500 } ] }

// response
{
  "job_id": "xxxxxxxx-...",
  "model_name": "Churn model",
  "count": 2,
  "predictions": [
    { "prediction": "yes", "confidence": 0.81, "warnings": ["'income' was missing; ..."] },
    { "prediction": "no",  "confidence": 0.93 }
  ]
}

To score a whole file without code, use Score a file on the model page (up to 10,000 rows or 500 images) and download the results as CSV.

GET /predict/{job_id}/schema

Describes the inputs a model expects, with an example body you can send as-is.

{
  "task_type": "classification",
  "target_column": "churned",
  "classes": ["no", "yes"],
  "inputs": [
    { "name": "age",  "type": "numeric", "median": 41, "min": 18, "max": 79 },
    { "name": "city", "type": "categorical", "values": ["austin", "boston", "chicago"], "mode": "austin" }
  ],
  "example": { "inputs": { "age": 41, "city": "austin" } }
}

Code examples

Replace JOB_ID and YOUR_API_KEY. The model page has ready-to-run snippets in nine languages, pre-filled with your model's columns.

Python (requests)

import requests

r = requests.post(
    "https://cletus-service.onrender.com/predict/JOB_ID",
    json={"inputs": {"age": 42, "city": "boston", "income": 61000}},
    headers={"X-API-Key": "YOUR_API_KEY"},
    timeout=30,
)
r.raise_for_status()
result = r.json()
print(result["prediction"], result["confidence"], result.get("warnings", []))

JavaScript / TypeScript

const res = await fetch("https://cletus-service.onrender.com/predict/JOB_ID", {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": "YOUR_API_KEY" },
  body: JSON.stringify({ inputs: { age: 42, city: "boston", income: 61000 } }),
});
if (!res.ok) throw new Error((await res.json()).error);
const { prediction, confidence } = await res.json();

cURL

curl -sS -X POST "https://cletus-service.onrender.com/predict/JOB_ID" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"inputs":{"age":42,"city":"boston","income":61000}}'

R (httr)

library(httr)
library(jsonlite)

res <- POST(
  "https://cletus-service.onrender.com/predict/JOB_ID",
  add_headers("X-API-Key" = "YOUR_API_KEY"),
  body = toJSON(list(inputs = list(age = 42, city = "boston", income = 61000)), auto_unbox = TRUE),
  content_type_json()
)
result <- content(res, "parsed")
cat(result$prediction, result$confidence, "\n")

How your data is prepared

The same steps run at training and at prediction time, so you always send raw values.

Task type

Text or two-valued targets train a classifier; continuous numbers train a regressor. Small whole-number targets are decided by the column name (e.g. "rating", "count" → regression; "class", "label" → classification) and then by their pattern.

Rows without a label

Rows whose target is empty are dropped before training (reported on the model page).

Columns dropped automatically

ID-like columns (id, uuid, anything ending in _id, "Unnamed: 0" index columns, 0..n row counters), date/time columns, and text columns with more than 100 distinct values (free text, names). The model page lists what was dropped.

Categories

Text columns are one-hot encoded. Send the original text; a value never seen in training has no effect and is reported in warnings.

Missing values

Numbers are filled with the training median and categories with the most common training value, both in the training data and in prediction requests.

Scaling

Numeric features are standardized with training-set statistics. Send unscaled values.

Evaluation

20% of rows are held out. The model page shows accuracy or R² on them, a naive baseline, a confusion matrix or predicted-vs-actual plot, and how much each input matters.

Rate limits & quotas

LimitValue
Predictions1,000 per account per calendar month (UTC) on the free plan. Batch and file scoring count every row.
Model slots5 models per account on the free plan. Sample-dataset models don't use a slot; delete a model to free one.
/predict, /batch, /schema60 requests per minute per IP (batch also 10 per minute)
Uploads / column checks10 training uploads and 30 file inspections per hour per IP
AI chat20 messages per 10 minutes per IP

Going over a rate limit or the monthly quota returns 429; creating a model with no free slot returns 403. Current usage is on the Usage page.

Other endpoints

GET /health — no auth

Liveness check: {"status":"ok","version":"…","timestamp":"…"}. Handy for waking the API before a burst of calls.

GET /jobs — Bearer

Your models with status, metrics, and call counts.

GET /jobs/{job_id} — Bearer

Full model detail: metrics, ml_report (training curve, dataset stats, evaluation), input_schema, example_inputs, and the API key (owner only).

POST /jobs/{job_id}/score-file — Bearer, multipart file

Score a whole file (any training format, up to 10,000 rows; a .zip of up to 500 images for image models). Returns the CSV with predictions plus a summary.

POST /jobs/{job_id}/rotate-api-key — Bearer

Invalidate the current key and issue a new one.

GET /jobs/{job_id}/predict-logs — Bearer

Recent prediction requests: timestamp, HTTP status, latency, success flag. Inputs and outputs are never logged.

POST /jobs/{job_id}/chat — Bearer

AI assistant for a model. Body: {"messages": [{"role": "user", "content": "…"}], "session_id": "…optional"}. It can run predictions for tabular models and explains metrics; conversations are saved as sessions.

Need help integrating?

The AI assistant on your model's page knows its exact columns and endpoint and can write working code for you.