Operation API
The Operation chat completions API. Grab a key, send a POST, get a reply. That's it.
Base URL
https://ai.vshll.lol/api/public/v1Authentication
Send your key in the Authorization header:
Authorization: Bearer drc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxGenerate keys at /api-keys. Keys are shown once on creation — store them somewhere safe.
POST /v1/chat/completions
Operation chat completions. Streaming and non-streaming supported.
Request body
model— model id. Default:google/gemini-3-flash-previewmessages— array of{ role, content }stream— boolean. SSE whentruetemperature,max_tokens,tools— optional, passed through
cURL
curl https://ai.vshll.lol/api/public/v1/chat/completions \
-H "Authorization: Bearer $OPERATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-3-flash-preview",
"messages": [
{ "role": "user", "content": "Hello, Operation!" }
]
}'Python (requests)
import os, requests
resp = requests.post(
"https://ai.vshll.lol/api/public/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['OPERATION_API_KEY']}",
"Content-Type": "application/json",
},
json={
"model": "google/gemini-3-flash-preview",
"messages": [{"role": "user", "content": "Hello, Operation!"}],
},
)
print(resp.json()["choices"][0]["message"]["content"])Node.js (fetch)
const res = await fetch("https://ai.vshll.lol/api/public/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.OPERATION_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "google/gemini-3-flash-preview",
messages: [{ role: "user", content: "Hello, Operation!" }],
}),
});
const data = await res.json();
console.log(data.choices[0].message.content);Streaming
Set "stream": true. The response is Server-Sent Events (SSE) with data: {...} chunks terminated by data: [DONE].
Models
google/gemini-3-flash-preview— fast, defaultgoogle/gemini-3-pro-preview— higher quality- Any model exposed by the upstream gateway. Pass it in
model.
Errors
Errors come back with a consistent JSON envelope:
{ "error": { "message": "…", "type": "invalid_api_key" } }401— missing/invalid/revoked key400— bad request body429— rate limited402— workspace credits exhausted
Tool calling
Pass a tools array describing the functions the model can call. If the model decides to use one, the response includes tool_calls. Run them on your side, then send the results back as role: "tool" messages on the next request and the model will continue from there.
Sign in with Operation
Build apps where users sign in with their Operation account, just like "Sign in with Google". The app gets an access token and calls the API on the user's behalf.
1. Register your app
Go to /api-keys → OAuth Apps → New app. Add one or more redirect_uris (must be https, or http://localhost for dev). You'll get a client_id and one-time client_secret.
2. Send the user to authorize
Redirect the user's browser to:
https://ai.vshll.lol/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=https://yourapp.com/callback
&state=RANDOM_STRINGstate is optional but recommended — generate a random value, store it, and check it on the redirect back to prevent CSRF.
The user signs in (if needed) and sees: "YourApp wants to access your Operation account." When they click Authorize, they're redirected to:
https://yourapp.com/callback?code=drcode_xxx&state=RANDOM_STRING3. Exchange the code for a token
On your server (never in browser code — protects your secret):
curl https://ai.vshll.lol/api/public/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"code": "drcode_xxx",
"redirect_uri": "https://yourapp.com/callback"
}'Response:
{ "access_token": "dro_xxxxxxxx…", "token_type": "Bearer" }4. Call the API as the user
Use the access token like any other Operation key:
curl https://ai.vshll.lol/api/public/v1/chat/completions \
-H "Authorization: Bearer dro_xxxxxxxx…" \
-H "Content-Type: application/json" \
-d '{ "model": "google/gemini-3-flash-preview", "messages": [{"role":"user","content":"hi"}] }'Tokens don't expire. Users can revoke an app's access anytime from their API keys page. If they do, the token starts returning 401.
Note
The API follows the widely-used chat-completions JSON format, so any OpenAI-compatible client library will work too if you prefer — just point its base URL at https://ai.vshll.lol/api/public/v1 and use your Operation key.
