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.
- 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.
- 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 alshttps://myapp.com. Paden, query strings en logins worden weggelaten. Een GitHub, GitLab, Codeberg, Bitbucket of Hugging Face link behoudt zijnowner/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
Referervanzelf, dus een web-app wordt geteld zelfs zonder de headers. VoegX-Titletoe 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_challengeis verplicht en alleenS256wordt geaccepteerd (OpenRouter accepteert ookplainof geen challenge). Zonder dit kan iedereen die de code ziet in een browsergeschiedenis of log de sleutel bemachtigen.workspace_id/required_workspace_idworden niet gebruikt: een UberLLM-account heeft één saldo.