Ứng dụng: được liệt kê và cho phép người dùng kết nối
Hai điều dành cho những người xây dựng ứng dụng trên UberLLM. Cả hai đều hoạt động giống như trên OpenRouter, vì vậy một ứng dụng đã thực hiện chúng chỉ cần thay đổi base URL.
- Được liệt kê. Gửi hai header và ứng dụng của bạn sẽ hiển thị trên uberllm.dev/apps, được xếp hạng theo số lượng token mà nó gửi. Các trang model liệt kê những ứng dụng sử dụng chúng nhiều nhất.
- Cho phép người dùng kết nối. Gửi người dùng đến UberLLM, họ đồng ý, và ứng dụng của bạn sẽ nhận được một API key trên tài khoản của họ. Họ tự thanh toán cho việc sử dụng của mình; bạn không bao giờ xử lý thông tin thanh toán của họ.
Được xếp hạng trên bảng xếp hạng ứng dụng
Thêm các header này vào yêu cầu của bạn (chat, tin nhắn hoặc media, bất kỳ endpoint nào):
| Header | Chức năng |
|---|---|
HTTP-Referer |
Địa chỉ ứng dụng của bạn, ví dụ https://myapp.com. Bắt buộc: đây là thứ nhận diện ứng dụng của bạn. Referer cũng hoạt động. |
X-Title |
Tên ứng dụng của bạn như mọi người sẽ thấy. X-OpenRouter-Title cũng hoạt động. |
X-OpenRouter-Categories |
Tùy chọn. Tối đa 2 danh mục bên dưới, phân tách bằng dấu phẩy. |
X-OpenRouter-App-Visibility |
Tùy chọn. hidden giữ một ứng dụng mới không xuất hiện trên bảng xếp hạng công khai. |
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"}]}'
Với 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',
},
});
Cách tính điểm:
- Chỉ địa chỉ được giữ lại:
https://myapp.com/some/page?user=…được lưu trữ dưới dạnghttps://myapp.com. Các paths, query strings và logins bị loại bỏ. Một liên kết GitHub, GitLab, Codeberg, Bitbucket hoặc Hugging Face giữ lạiowner/repocủa nó, vì vậy các ứng dụng mã nguồn mở có mục riêng. - Tên được cắt ngắn còn 60 ký tự. Các ký tự ẩn và ký tự điều khiển bị loại bỏ.
- Tài khoản đầu tiên gửi traffic cho một ứng dụng sẽ đặt tên và danh mục của ứng dụng đó. Traffic từ các tài khoản khác vẫn được tính cho ứng dụng, nhưng không thể đổi tên ứng dụng.
- Các địa chỉ trên máy hoặc mạng của riêng bạn (
localhost,127.0.0.1, private IPs,*.local) không bao giờ được hiển thị công khai. - Các yêu cầu từ trình duyệt tự động gửi
Referer, vì vậy một ứng dụng web vẫn được tính ngay cả khi không có các header. ThêmX-Titleđể chọn tên của nó. - Bảng xếp hạng tính các yêu cầu đã được trả lời, theo tokens, trong 24 giờ, 7 ngày hoặc 30 ngày gần nhất. Bảng xếp hạng này làm mới sau mỗi vài phút.
Danh mục: 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. Các danh mục không xác định sẽ bị bỏ qua. Một ứng dụng giữ tối đa 10.
Bảng xếp hạng cũng là một API: GET https://uberllm.dev/api/v1/public/apps?period=day|week|month&category=<slug>.
Kết nối UberLLM (OAuth PKCE)
Ứng dụng của bạn nhận một khóa trên tài khoản của người dùng, được đặt tên theo ứng dụng của bạn. Người dùng có thể đặt giới hạn chi tiêu cho khóa đó khi cho phép, và có thể tắt nó bất cứ lúc nào trên trang khóa của họ.
1. Tạo bộ xác minh và thử thách mã
Bộ xác minh là một chuỗi ngẫu nhiên bạn giữ (43 đến 128 ký tự). Thử thách là SHA-256, base64url-encoded của nó, không có phần đệm.
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. Gửi người dùng đến UberLLM
https://uberllm.dev/auth?callback_url=https://myapp.com/uberllm/callback&code_challenge=<CHALLENGE>&code_challenge_method=S256
| Tham số | |
|---|---|
callback_url |
Nơi người dùng quay lại. Phải là https://; http://localhost (bất kỳ cổng nào) được phép cho mục đích phát triển. Để trống để hiển thị mã trên màn hình cho người dùng dán vào ứng dụng của bạn. |
code_challenge |
Từ bước 1. Bắt buộc. |
code_challenge_method |
S256. Bắt buộc. plain không được chấp nhận. |
key_label |
Tên tùy chọn cho khóa (mặc định: tên ứng dụng của bạn). |
state |
Tùy chọn. Được gửi lại nguyên vẹn cùng với mã, để bạn có thể kiểm tra xem phản hồi có thuộc về yêu cầu bạn đã bắt đầu hay không. |
Người dùng đăng nhập (hoặc đăng ký), thấy "Ứng dụng của bạn muốn sử dụng tín dụng UberLLM của bạn", và chọn Cho phép hoặc Hủy bỏ. Khi Cho phép, họ được gửi đến:
https://myapp.com/uberllm/callback?code=<CODE>&state=<STATE>
Khi Hủy bỏ, không có gì được gửi đi đâu cả.
3. Đổi mã lấy khóa
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"}'
Phản hồi là {"key": "ull_…", "key_id": "…", "name": "My App"}. Sử dụng khóa làm Authorization: Bearer trên https://api.uberllm.dev/v1. Endpoint trả lời các yêu cầu trình duyệt từ bất kỳ trang web nào (CORS), vì vậy nó hoạt động từ một ứng dụng web.
| Trạng thái | Mã | Ý nghĩa |
|---|---|---|
| 400 | invalid_code_challenge_method |
Sử dụng S256. |
| 403 | invalid_code |
Mã sai hoặc code_verifier, hoặc mã đã được sử dụng. |
| 403 | code_expired |
Mã có hiệu lực trong 10 phút. Bắt đầu lại từ bước 2. |
| 405 | method_not_allowed |
Sử dụng POST. |
| 429 | rate_limited |
Quá nhiều lần thử từ một địa chỉ; đợi một phút. |
Một mã chỉ hoạt động một lần. Một code_verifier sai cũng làm mã bị sử dụng hết, vì vậy mã bị lộ không thể bị đoán.
Điểm khác biệt so với OpenRouter
code_challengelà bắt buộc và chỉS256được chấp nhận (OpenRouter cũng chấp nhậnplainhoặc không có thử thách). Nếu không có nó, bất kỳ ai nhìn thấy mã trong lịch sử trình duyệt hoặc nhật ký đều có thể lấy khóa.workspace_id/required_workspace_idkhông được sử dụng: một tài khoản UberLLM có một số dư.