앱: 등록하고 사용자들이 연결하게 하세요
UberLLM에서 앱을 개발하는 분들을 위한 두 가지가 있습니다. 둘 다 OpenRouter에서와 동일하게 작동하므로, 이미 이 기능을 사용하는 앱은 base URL만 변경하면 됩니다.
- 등록하세요. 두 개의 header를 보내면 앱이 uberllm.dev/apps에 표시되며, 전송하는 token 수에 따라 순위가 매겨집니다. 모델 페이지에는 해당 모델을 가장 많이 사용하는 앱이 나열됩니다.
- 사용자들이 연결하게 하세요. 사용자들을 UberLLM으로 보내세요. 그들이 동의하면, 앱은 그들의 계정으로 API key를 받습니다. 그들은 자신의 사용량에 대해 비용을 지불하며, 당신은 그들의 결제 정보를 절대 처리하지 않습니다.
앱 순위에 등록하세요
요청(채팅, 메시지 또는 미디어, 모든 endpoint)에 다음 헤더를 추가하세요:
| 헤더 | 기능 |
|---|---|
HTTP-Referer |
앱 주소, 예: https://myapp.com. 필수: 앱을 식별하는 데 사용됩니다. Referer도 작동합니다. |
X-Title |
사람들이 보게 될 앱 이름. X-OpenRouter-Title도 작동합니다. |
X-OpenRouter-Categories |
선택 사항. 아래 카테고리 중 최대 2개까지 쉼표로 구분하여 입력. |
X-OpenRouter-App-Visibility |
선택 사항. hidden는 새 앱을 공개 순위에서 제외합니다. |
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"}]}'
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',
},
});
계산 방식:
- 주소만 유지됩니다:
https://myapp.com/some/page?user=…은https://myapp.com로 저장됩니다. 경로, 쿼리 문자열 및 로그인은 삭제됩니다. GitHub, GitLab, Codeberg, Bitbucket 또는 Hugging Face 링크는owner/repo를 유지하므로 오픈 소스 앱은 자체 항목을 가집니다. - 이름은 60자로 잘립니다. 숨겨진 문자 및 제어 문자는 제거됩니다.
- 앱에 트래픽을 보내는 첫 번째 계정이 앱의 이름과 카테고리를 설정합니다. 다른 계정의 트래픽도 해당 앱에 대해 계산되지만, 이름을 변경할 수는 없습니다.
- 사용자 자신의 머신 또는 네트워크(
localhost,127.0.0.1, private IPs,*.local)의 주소는 절대 공개적으로 표시되지 않습니다. - 브라우저의 요청은 자체적으로
Referer를 보내므로, 헤더 없이도 웹 앱이 계산됩니다. 이름을 선택하려면X-Title를 추가하세요. - 순위는 지난 24시간, 7일 또는 30일 동안 토큰별로 응답된 요청을 계산합니다. 몇 분마다 새로 고쳐집니다.
카테고리: 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. 알 수 없는 카테고리는 무시됩니다. 앱은 최대 10개를 유지합니다.
순위는 API로도 제공됩니다: GET https://uberllm.dev/api/v1/public/apps?period=day|week|month&category=<slug>.
UberLLM 연결 (OAuth PKCE)
사용자의 계정에 앱 이름으로 된 키가 발급됩니다. 사용자는 키를 허용하는 동안 지출 한도를 설정할 수 있으며, 언제든지 키 페이지]에서 끌 수 있습니다.
1. 코드 검증자 및 챌린지 생성
검증자는 (43에서 128자 사이의) 임의의 문자열이며, 이를 보관해야 합니다. 챌린지는 패딩 없이 SHA-256, base64url-인코딩된 검증자입니다.
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. 사용자를 UberLLM으로 보내기
https://uberllm.dev/auth?callback_url=https://myapp.com/uberllm/callback&code_challenge=<CHALLENGE>&code_challenge_method=S256
| 매개변수 | |
|---|---|
callback_url |
사용자가 돌아올 주소입니다. https://여야 합니다. 개발용으로는 http://localhost (모든 포트)가 허용됩니다. 사용자가 앱에 붙여넣을 수 있도록 코드를 화면에 표시하려면 이 값을 생략하세요. |
code_challenge |
1단계에서 얻은 값입니다. 필수입니다. |
code_challenge_method |
S256. 필수입니다. plain는 허용되지 않습니다. |
key_label |
키의 선택적 이름 (기본값: 앱 이름). |
state |
선택 사항입니다. 시작한 요청에 대한 응답인지 확인할 수 있도록 코드와 함께 변경되지 않고 다시 전송됩니다. |
사용자는 로그인(또는 가입)하고, '귀하의 앱이 UberLLM 크레딧을 사용하려고 합니다'라는 메시지를 본 후, 허용 또는 취소를 선택합니다. 허용 시 다음으로 이동합니다:
https://myapp.com/uberllm/callback?code=<CODE>&state=<STATE>
취소 시에는 아무것도 전송되지 않습니다.
3. 코드를 키로 교환
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"}'
응답은 {"key": "ull_…", "key_id": "…", "name": "My App"}입니다. 키를 https://api.uberllm.dev/v1에서 Authorization: Bearer로 사용하세요. 이 엔드포인트는 모든 사이트의 브라우저 요청(CORS)에 응답하므로 웹 앱에서도 작동합니다.
| 상태 | 코드 | 의미 |
|---|---|---|
| 400 | invalid_code_challenge_method |
S256를 사용하세요. |
| 403 | invalid_code |
잘못된 코드 또는 code_verifier, 또는 코드가 이미 사용되었습니다. |
| 403 | code_expired |
코드는 10분 동안 유효합니다. 2단계부터 다시 시작하세요. |
| 405 | method_not_allowed |
POST를 사용하세요. |
| 429 | rate_limited |
한 주소에서 너무 많은 시도; 1분 기다리세요. |
코드는 한 번만 작동합니다. 잘못된 code_verifier도 코드를 소모하므로, 유출된 코드는 추측 공격에 사용될 수 없습니다.
OpenRouter와의 차이점
code_challenge는 필수이며S256만 허용됩니다 (OpenRouter는plain또는 챌린지 없음도 허용합니다). 이것이 없으면 브라우저 기록이나 로그에서 코드를 본 사람이 키를 가져갈 수 있습니다.workspace_id/required_workspace_id는 사용되지 않습니다: UberLLM 계정은 하나의 잔액을 가집니다.