Documentation menu

Use with curl

Everything the L80 CLI does on launch80 goes through a small HTTP API, so curl and a token are enough to publish, list pages in the Directory and get verified. Nothing to install.

Needs a token

curl or the CLI

Both reach the same pages. What changes is who does the safety work:

curlL80 CLI
Installnothingone binary
Templateyou write "$template" into the JSON--template, or "$template"
Private fieldsyou remove env.endpoint and env.host; the server refuses themstripped for you
Check before publishingGET the template schema--dry-run
Verification checksthe server answers with any that failL80 verify check, offline, first
Record of what you publishedGET /api/v1/artifactsthat, plus a local ledger of source files
Run BetterBench, reproduce a runrun the tools yourselfL80 betterbench, L80 verify reproduce

The guides show both: each command block has an L80 CLI | curl switch, and your choice is remembered on every page. The full endpoint list is in the HTTP API reference.

Set up

A token comes with the Supporter role and is emailed to you. Put it in the environment without leaving it in your shell history, then check it:

$ read -rs L80_TOKEN && export L80_TOKEN    # paste the token, then enter$ curl -sS https://www.launch80.com/api/v1/keys/me -H "Authorization: Bearer $L80_TOKEN"

The answer is {"ok":true,"data":{"key_id":…,"label":…,"is_verifier":…}}. Examples pipe through jq where it helps; it is optional.

Publish

Pick a layout from Templates (each links to a complete valid payload) and name it in the JSON as "$template". Check the payload against the template's schema if you like, then post the file as is:

$ curl -sS https://www.launch80.com/api/v1/templates | jq '.data[].id'$ curl -sS https://www.launch80.com/api/v1/templates/bench.report.v1/schema | jq .data > schema.json$ curl -sS -X POST https://www.launch80.com/api/v1/artifacts \  -H "Authorization: Bearer $L80_TOKEN" \  -H "Content-Type: application/json" \  --data-binary @report.json | jq .data

The answer carries url (the page), guid and content_hash (keep the last two if you will ask for verification), and says what happened: message (who can see the page), next (how to list or unlist it, how to request verification, each as the HTTP call) and quota (publishes left today). Use --data-binary, not -d, so the bytes arrive unchanged. 10 publishes per key per day; pages are kept 5 days.

A BetterBench run

Publish a BetterBench results.json as written, with the template added and the two private fields removed (the schema rejects them):

$ jq '. + {"$template": "bench.betterbench.v1"} | del(.env.endpoint, .env.host)' results.json > payload.json$ curl -sS -X POST "https://www.launch80.com/api/v1/artifacts?listed=true" \  -H "Authorization: Bearer $L80_TOKEN" \  -H "Content-Type: application/json" \  --data-binary @payload.json | jq .data.url

When BetterBench ran on another machine it records no GPU. Add one as a note so the Directory can filter by it: | .env.notes.gpu = "RTX 4090" in the jq filter. Leave out ?listed=true to keep the page unlisted. The page shows your key id as its author; add &author=false (or ?author=false) to leave it off.

List in the Directory

Pages are unlisted, reachable only by their link, until you list them in the Directory. List one as you publish with ?listed=true, or later, in either direction, with the guid from its URL:

$ curl -sS -X PUT https://www.launch80.com/api/v1/artifacts/<guid>/visibility \  -H "Authorization: Bearer $L80_TOKEN" \  -H "Content-Type: application/json" \  -d '{"listed": true}'

{"listed": false} takes it out. Only the publishing key can do either, and only for benchmark and scan templates (not generic.report.v1). A listed page shows up within a minute.

History

$ curl -sS "https://www.launch80.com/api/v1/artifacts?limit=50" -H "Authorization: Bearer $L80_TOKEN" \  | jq -r '.data.artifacts[] | [.created_at, .template_id, .trust_tier, (if .listed then "listed" else "-" end), .url] | @tsv'

Newest first, up to 200 per call. When a full page comes back, data.next_before is set: pass it as &before=… for the next. Filter in jq, e.g. select(.listed) or select(.trust_tier == "verified").

Get verified

Verification is open to bench.betterbench.v1 and scan.pwdet.v1 pages. Send the hashes of what you published so the provenance check can match them; without them it warns rather than fails:

$ jq -n --arg note "vLLM 0.9.3, --max-model-len 32768" \  --arg body "$(shasum -a 256 payload.json | cut -d' ' -f1)" \  --arg hash "<content_hash from the publish answer>" \  '{note: $note, body_sha256: $body, content_hash: $hash}' > request.json$ curl -sS -X POST https://www.launch80.com/api/v1/artifacts/<guid>/verification \  -H "Authorization: Bearer $L80_TOKEN" \  -H "Content-Type: application/json" \  --data-binary @request.json | jq .data.status$ curl -sS https://www.launch80.com/api/v1/artifacts/<guid>/verification -H "Authorization: Bearer $L80_TOKEN" | jq .data.status$ curl -sS "https://www.launch80.com/api/v1/verifications?scope=mine" -H "Authorization: Bearer $L80_TOKEN"
  • 201: the page turns pending and the request joins the queue. A failed server check answers E_VERIFY_INELIGIBLE (422), one details entry per check: fix the run, publish again, request again.
  • The checks are listed in Get verified. Ten requests per key per day.

Review others

Any key can read the queue and download a run to reproduce it with BetterBench on its own hardware:

$ curl -sS "https://www.launch80.com/api/v1/verifications?scope=queue" -H "Authorization: Bearer $L80_TOKEN" | jq '.data[] | {id, title, url}'$ curl -sS https://www.launch80.com/api/v1/artifacts/<guid>/payload | jq .data > published-results.json

Verifier keys A verifier decides; a rejection needs a note, which the publisher sees:

$ curl -sS -X POST https://www.launch80.com/api/v1/verifications/<id>/decision \  -H "Authorization: Bearer $L80_TOKEN" \  -H "Content-Type: application/json" \  -d '{"decision": "verified", "note": "matched on 1x RTX 4090"}'

Approving a pwdet scan needs the reproduction pwdet writes. The body is in the API reference.

Responses and errors

Every answer is {"ok": true, "data": …} or {"ok": false, "error": {"code", "message", "remedy", "details"?, "request_id"}}. The remedy says what to change; details points at the exact field. A 429 carries Retry-After. Every code.