Every trained model ships as a secured REST endpoint. Call it from any language or framework — no SDK required.
.zip with one folder per class for images.complete).POST /predict/{job_id} with the raw values of your input columns.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.
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.
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
| Status | Meaning |
|---|---|
| 400 | Model not ready, or an input has the wrong type (e.g. text for a numeric column) |
| 401 | Missing or invalid X-API-Key |
| 403 | The key belongs to a different model |
| 413 | Request body too large (15 MB for /predict, 1 MB for most other endpoints) |
| 422 | Malformed body (e.g. inputs is not an object, more than 1,000 batch rows) |
| 429 | Rate limit or monthly prediction quota reached — see Rate limits & quotas |
| 500 | Server error (e.g. model files missing) |
Every error body is { "error": "description" }.
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.
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.
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" } }
}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")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.
| Limit | Value |
|---|---|
| Predictions | 1,000 per account per calendar month (UTC) on the free plan. Batch and file scoring count every row. |
| Model slots | 5 models per account on the free plan. Sample-dataset models don't use a slot; delete a model to free one. |
| /predict, /batch, /schema | 60 requests per minute per IP (batch also 10 per minute) |
| Uploads / column checks | 10 training uploads and 30 file inspections per hour per IP |
| AI chat | 20 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.
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.