onrup

Docs

Quickstart

How do I fine-tune and deploy a model on Onrup?

Create an account with a magic link, upload a JSONL dataset, submit a run against a template, gate the result against your baseline, then create an endpoint. Five API calls end to end, and the cost is authorised before any compute is leased.

Get a key

Sign-in and sign-up are the same action. Request a magic link, redeem it, and the first redemption creates your user, your tenant and your first API key. There is no password and no card until you ask for compute.

curl https://api.onrup.com/v1/auth/magic-link \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'

Upload a dataset

Uploads are resumable and go directly to storage — the API hands back presigned URLs and the bytes never pass through it. That matters for anything above a few hundred megabytes, and it means an interrupted upload resumes rather than restarts.

Completing the upload triggers validation. This is the cheapest place in the whole process to find a problem, and it costs nothing.

curl https://api.onrup.com/v1/data-assets/uploads \
  -H "Authorization: Bearer $ONRUP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "training_full",
    "filename": "support-triage.jsonl",
    "size_bytes": 48210394,
    "source_format": "jsonl-sharegpt"
  }'

Read the validation report

Do not skip this. The report gives record counts, token length percentiles, the duplicate rate and — most importantly — how many examples would be truncated at your intended sequence length. Truncation is silent during training and produces a model that stops mid-answer.

curl https://api.onrup.com/v1/data-assets/$ASSET_ID/report \
  -H "Authorization: Bearer $ONRUP_API_KEY"

Forecast, then submit

A run is created in draft and does nothing until it is submitted. Submission is where cost is estimated, reserved against your spend limit, and the job queued — or rejected, if it would breach the limit.

That ordering is the point. A run that would cost more than you have authorised does not start and then get stopped; it does not start.

# What will this cost?
curl "https://api.onrup.com/v1/forecast/cost?model=qwen3-8b&template=qwen3-8b-sft-lora-fast&dataset_size=48210394" \
  -H "Authorization: Bearer $ONRUP_API_KEY"

# Create and submit
RUN=$(curl -s https://api.onrup.com/v1/runs \
  -H "Authorization: Bearer $ONRUP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template": "qwen3-8b-sft-lora-fast", "data_asset_id": "'$ASSET_ID'"}' | jq -r .id)

curl https://api.onrup.com/v1/runs/$RUN/submit \
  -X POST -H "Authorization: Bearer $ONRUP_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Watch it

Progress is a server-sent event stream, and it is resumable — a client that drops can reconnect and replay from the last event it saw rather than losing the history. Polling the event log with a cursor gives exactly the same information for callers that would rather not hold a connection open.

curl -N https://api.onrup.com/v1/runs/$RUN/stream \
  -H "Authorization: Bearer $ONRUP_API_KEY"

Gate it before you trust it

A finished run is a candidate, not a decision. The gate scores it blinded against whatever is running today, on held-out cases from your own data, and returns pass, fail or inconclusive. Only a pass unlocks a deploy or a publish.

curl https://api.onrup.com/v1/evaluations \
  -H "Authorization: Bearer $ONRUP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "candidate_run_id": "'$RUN'",
    "baseline": {"kind": "deployment", "id": "'$CURRENT_DEPLOYMENT'"},
    "evaluation_asset_id": "'$EVAL_ASSET'",
    "max_cost_usd": 8.00
  }'

Serve it

Creating a deployment gives you an OpenAI-compatible endpoint. The one decision that matters is the replica floor: zero means the endpoint costs nothing when idle and pays a cold start on the first request after a quiet period; one or more means no cold starts and a continuous hourly charge.

curl https://api.onrup.com/v1/deployments \
  -H "Authorization: Bearer $ONRUP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "run_id": "'$RUN'",
    "slug": "support-triage",
    "gpu_class": "rtx-4090-24g",
    "min_replicas": 0,
    "cooldown_seconds": 600
  }'

Frequently asked questions

How long does a first fine-tune take?

A LoRA run on an 8B model over a few thousand examples is typically well under an hour of GPU time. The wall time also includes waiting for capacity in your chosen class, which the forecast endpoint indicates before you commit.

What does it cost to try?

Account creation, upload and validation are free. The first real cost is the training run, which is forecast before submission and reserved against a limit you set — so the answer is never a surprise.

Start with the free tier

A magic link creates your account, your tenant and your first API key. No card until you ask for compute.