NieuwKoppel elke agent aan UberLLM: één sleutel, elk model, voor de catalogusprijs of minder.
UberLLM

Apps: word vermeld en laat gebruikers verbinden

Twee dingen voor mensen die apps bouwen op UberLLM. Beide werken op dezelfde manier als op OpenRouter, dus een app die ze al doet, hoeft alleen de base URL te wijzigen.

  1. Word vermeld. Stuur twee headers en je app verschijnt op uberllm.dev/apps, gerangschikt op de tokens die het verstuurt. Modelpagina's vermelden de apps die ze het meest gebruiken.
  2. Laat gebruikers verbinden. Stuur gebruikers naar UberLLM, zij zeggen ja, en je app krijgt een API key op hun account. Zij betalen voor hun eigen gebruik; jij beheert nooit hun betalingsgegevens.

Word vermeld in de app-ranglijst

Voeg deze headers toe aan je verzoeken (chat, berichten of media, elk endpoint):

Header Wat het doet
HTTP-Referer Het adres van je app, bijv. https://myapp.com. Verplicht: dit identificeert je app. Referer werkt ook.
X-Title De naam van je app zoals mensen die moeten zien. X-OpenRouter-Title werkt ook.
X-OpenRouter-Categories Optioneel. Maximaal 2 van de onderstaande categorieën, kommagescheiden.
X-OpenRouter-App-Visibility Optioneel. hidden houdt een nieuwe app buiten de openbare ranglijst.
curl https://api.uberllm.dev/v1/chat/completions \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "HTTP-Referer: https://myapp.com" \
  -H "X-Title: My App" \
  -H "X-OpenRouter-Categories: cli-agent" \
  -d '{"model":"deepseek/deepseek-v4-flash","messages":[{"role":"user","content":"Hello"}]}'

Met de OpenAI SDK:

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://api.uberllm.dev/v1',
  apiKey: process.env.UBERLLM_API_KEY,
  defaultHeaders: {
    'HTTP-Referer': 'https://myapp.com',
    'X-Title': 'My App',
  },
});

Hoe het wordt geteld:

  • Alleen het adres wordt bewaard: https://myapp.com/some/page?user=… wordt opgeslagen als https://myapp.com. Paden, query strings en logins worden weggelaten. Een GitHub, GitLab, Codeberg, Bitbucket of Hugging Face link behoudt zijn owner/repo, zodat open-source apps hun eigen vermelding krijgen.
  • De naam wordt ingekort tot 60 tekens. Verborgen en controle tekens worden verwijderd.
  • Het eerste account dat verkeer voor een app stuurt, stelt de naam en categorieën in. Het verkeer van andere accounts telt nog steeds mee voor de app, maar kan deze niet hernoemen.
  • Adressen op je eigen machine of netwerk (localhost, 127.0.0.1, private IPs, *.local) worden nooit openbaar getoond.
  • Verzoeken van browsers sturen Referer vanzelf, dus een web-app wordt geteld zelfs zonder de headers. Voeg X-Title toe om de naam te kiezen.
  • De ranglijst telt verzoeken die zijn beantwoord, per tokens, over de laatste 24 uur, 7 dagen of 30 dagen. Deze wordt elke paar minuten vernieuwd.

Categorieën: cli-agent, ide-extension, cloud-agent, programming-app, native-app-builder, creative-writing, video-gen, image-gen, audio-gen, writing-assistant, general-chat, personal-agent, legal, roleplay, game. Onbekende worden genegeerd. Een app behoudt maximaal 10.

De ranglijst is ook een API: GET https://uberllm.dev/api/v1/public/apps?period=day|week|month&category=<slug>.

Verbind UberLLM (OAuth PKCE)

Je app krijgt een sleutel op het eigen account van de gebruiker, genoemd naar je app. De gebruiker kan er een bestedingslimiet voor instellen terwijl deze wordt toegestaan, en kan deze op elk moment uitschakelen op hun sleutels-pagina.

1. Maak een code-verifier en challenge

De verifier is een willekeurige string die je bewaart (43 tot 128 tekens). De challenge is de SHA-256, base64url-gecodeerd zonder padding.

function base64url(bytes) {
  return btoa(String.fromCharCode(...new Uint8Array(bytes)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

const codeVerifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const codeChallenge = base64url(
  await crypto.subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier)),
);
sessionStorage.setItem('uberllm_verifier', codeVerifier);

2. Stuur de gebruiker naar UberLLM

https://uberllm.dev/auth?callback_url=https://myapp.com/uberllm/callback&code_challenge=<CHALLENGE>&code_challenge_method=S256
Parameter
callback_url Waar de gebruiker naar terugkeert. Moet https:// zijn; http://localhost (elke poort) is toegestaan voor ontwikkeling. Laat het weg om de code op het scherm te tonen zodat de gebruiker deze in je app kan plakken.
code_challenge Van stap 1. Verplicht.
code_challenge_method S256. Verplicht. plain wordt niet geaccepteerd.
key_label Optionele naam voor de sleutel (standaard: naam van je app).
state Optioneel. Wordt ongewijzigd teruggestuurd met de code, zodat je kunt controleren of het antwoord bij de door jou gestarte aanvraag hoort.

De gebruiker logt in (of meldt zich aan), ziet "Je app wil je UberLLM-tegoed gebruiken", en kiest Toestaan of Annuleren. Bij Toestaan worden ze gestuurd naar:

https://myapp.com/uberllm/callback?code=<CODE>&state=<STATE>

Bij Annuleren wordt er niets ergens naartoe gestuurd.

3. Wissel de code in voor een sleutel

const code = new URLSearchParams(location.search).get('code');
const res = await fetch('https://uberllm.dev/api/v1/auth/keys', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    code,
    code_verifier: sessionStorage.getItem('uberllm_verifier'),
    code_challenge_method: 'S256',
  }),
});
const { key } = await res.json(); // ull_…  Store it like a password.
curl https://uberllm.dev/api/v1/auth/keys \
  -H "Content-Type: application/json" \
  -d '{"code":"<CODE>","code_verifier":"<VERIFIER>","code_challenge_method":"S256"}'

Het antwoord is {"key": "ull_…", "key_id": "…", "name": "My App"}. Gebruik de sleutel als Authorization: Bearer op https://api.uberllm.dev/v1. De endpoint beantwoordt browserverzoeken van elke site (CORS), dus het werkt vanuit een web-app.

Status Code Betekenis
400 invalid_code_challenge_method Gebruik S256.
403 invalid_code Verkeerde code of code_verifier, of de code is al gebruikt.
403 code_expired Codes werken 10 minuten. Begin opnieuw vanaf stap 2.
405 method_not_allowed Gebruik POST.
429 rate_limited Te veel pogingen vanaf één adres; wacht een minuut.

Een code werkt één keer. Een verkeerde code_verifier verbruikt deze ook, dus een code die is gelekt kan niet worden geraden.

Verschillen met OpenRouter

  • code_challenge is verplicht en alleen S256 wordt geaccepteerd (OpenRouter accepteert ook plain of geen challenge). Zonder dit kan iedereen die de code ziet in een browsergeschiedenis of log de sleutel bemachtigen.
  • workspace_id / required_workspace_id worden niet gebruikt: een UberLLM-account heeft één saldo.