Bosphorus

← Knowledge base

Calling the API with your own keys: Evren and tool servers

Call the API as yourself so your own Evren key and tool tokens apply: get a personal key on My variables, save your keys, call models and tools.

APIMy variablesEvrenToolsChecked against the product on

Three ways to reach your Evren key

The same request for an EV/ model, from aimo, from the VS Code extension and from an app of your own. Only the way it proves who you are changes.

aimo, the chat workspace

aimo signs each turn for you, so its shared connection still carries who you are.

  1. YouYou sign in to aimo with your company account and pick an EV/ model.Sends on your message
  2. aimoClientaimo adds its own service key and a short-lived token, signed for you.Sends on service key + your signed token
  3. GatewayThe gateway checks the signature and knows it is you. Your personal limits apply.Sends on who you are
  4. Your vaultYour Evren key is read for this one call.Sends on your Evren key
  5. EvrenEvren answers in the chat. Usage is recorded under your name.

Without an Evren key: aimo shows the reason as a chat message, with a link to My variables, and the conversation stays open.

aimo for VS Code

The extension holds a personal key of its own, minted when you sign in.

  1. YouYou sign in once with a device code.Sends on your request
  2. VS CodeClientThe extension sends your personal key, kept in VS Code's secret storage.Sends on your personal key
  3. GatewayThe gateway resolves the key to you. Your limits apply.Sends on who you are
  4. Your vaultYour Evren key is read for this one call.Sends on your Evren key
  5. EvrenEvren answers in the editor. Usage is recorded under your name.

Without an Evren key: The chat panel shows the gateway's reason and offers Select model.

Your app, with each person's own key

Each person gets a personal key once, and your app sends it with their requests.

  1. YouThe person gets a personal key once, from a sign-in.Sends on their request
  2. Your appClientYour app sends that person's key as the Bearer.Sends on their personal key
  3. GatewayThe gateway resolves the key to that person. Their limits apply.Sends on who they are
  4. Your vaultTheir Evren key is read for this one call.Sends on their Evren key
  5. EvrenEvren answers your app. Usage is recorded under their name.

Without an Evren key: HTTP 503 with the reason. Show it, and point the person to My variables.

Your app, with one team key

A team key names a team, not a person, so there is no Evren key to read.

  1. YouPeople use your app.Sends on a request
  2. Your appClientYour app sends the same team key for everyone.Sends on team key
  3. Gateway503The gateway finds no person behind the key and answers 503.
  4. Your vaultNo vault is read.Never reached
  5. EvrenEvren is never called.Never reached

What happens instead: Every EV/ call answers 503: this request carries no user identity. Models that do not need your own key still work with a team key.

What differs
aimoVS CodeAPI, personal keyAPI, team key
How you sign inCompany account, in the browserDevice code, onceDevice code, once per personNot at all
What the request carriesaimo's key + your signed tokenYour personal keyThat person's keyOne team key
Who the gateway seesYouYouThat personNo one
Evren key usedYoursYoursTheirsNone: 503

In every case you save the Evren key once, on My variables, and no client ever holds it. aimo can sign for whoever is signed in because the platform trusts it to; an outside app is not given that power, so it sends each person's own key.

Some models and tool servers on the platform run on your own keys. Evren models use your Evren key. GitHub, Context7 and O’Reilly use your own token. You keep those keys on My variables, and an API call never carries them: the gateway reads them for the person the call identifies, on each call. So the one thing a script must get right is who it is.

The figure above compares the same Evren request from aimo, from the VS Code extension and from an app of your own. This article shows how to call the API as yourself, save your keys, and call Evren models and tool servers with them. Every command below was run against a live installation on 30 September 2026, and the answers quoted are the ones it gave.

Who does what

Step Who Where
Register the Evren models Administrator Console, /providers → Evren
Register tool servers and declare their variables Administrator Console, /mcp; see the OpenBao keys article
Get a personal API key Each person My variables (/vault), once; or a terminal
Save their Evren key and tool variables Each person My variables (/vault)
Call models and tools Each person Any HTTP client, SDK or MCP client

How a call finds your key

  1. Your script sends your personal platform key, gpk_…, as the Bearer.
  2. The gateway resolves that key to you. Your quota, rate limits and policy apply.
  3. It reads your Evren key or your tool variable from your vault.
  4. It sends that key to Evren or to the tool server, for this one call.

Your script only ever holds the personal platform key. A team or service key cannot do this: it names a team, not a person, so there is no vault to read.

Part A: once, for each person

A1. Get your personal API key

The quickest way is the console. Sign in, open My variables (/vault) and press Create my API key on the My API key card at the top.

Treat it like a password: anyone holding it acts as you, on your own Evren and tool keys. The check at the end of this section works for a key from either route.

From a terminal instead

If your account cannot open the console, or you would rather script it, mint the key from a sign-in with your company account, using a device code. You need curl and jq. First read how your installation signs people in:

GW=https://ai.corp.example
CFG=$(curl -s $GW/api/identity/config)
echo "$CFG" | jq '{entra: (.entra != null), oidc: .oidc.provider}'

If entra is true, the installation signs in with Microsoft Entra ID:

TENANT=$(echo "$CFG" | jq -r .entra.tenantId)
CLIENT=$(echo "$CFG" | jq -r .entra.clientId)
SCOPE=$(echo "$CFG" | jq -r .entra.scope)
DA=https://login.microsoftonline.com/$TENANT/oauth2/v2.0/devicecode
TE=https://login.microsoftonline.com/$TENANT/oauth2/v2.0/token

If oidc is generic, it signs in with its own OpenID Connect provider, such as Keycloak, and the same document names the endpoints:

CLIENT=$(echo "$CFG" | jq -r .oidc.clientId)
SCOPE="openid profile email $(echo "$CFG" | jq -r .oidc.apiScope)"
DA=$(echo "$CFG" | jq -r .oidc.endpoints.deviceAuthorization)
TE=$(echo "$CFG" | jq -r .oidc.endpoints.token)

Then start the sign-in:

DC=$(curl -s $DA -d client_id=$CLIENT --data-urlencode "scope=$SCOPE")
echo "$DC" | jq -r '.message // .verification_uri_complete'

Open the address it prints, enter the code if one is shown, and sign in. Then, in the same terminal, collect the token and exchange it for your key:

TOKEN=$(curl -s $TE -d grant_type=urn:ietf:params:oauth:grant-type:device_code \
  -d client_id=$CLIENT -d device_code=$(echo "$DC" | jq -r .device_code) | jq -r .access_token)
curl -s -X POST "$GW/api/identity/token?client=api" -H "Authorization: Bearer $TOKEN" | jq -r .key.key

Check who the platform thinks you are:

curl -s $GW/api/identity/me -H "Authorization: Bearer $BOSPHORUS_KEY" | jq .user.email

It prints your address. With a team key it prints null, and the answer’s note reads no user identity presented.

A2. Save your keys on My variables

Sign in to the console and open My variables (/vault).

The Evren key can also be managed from a script with your personal key. PUT saves it, GET shows its state with your quota and balance, and DELETE removes it (add ?kind=llm or ?kind=platform to remove only one):

jq -n --arg k "$EVREN_LLM_KEY" '{api_key: $k}' |
  curl -s -X PUT $GW/api/identity/evren-key \
    -H "Authorization: Bearer $BOSPHORUS_KEY" -H 'Content-Type: application/json' -d @- | jq
curl -s $GW/api/identity/evren-key -H "Authorization: Bearer $BOSPHORUS_KEY" | jq 'keys'

The GET answers with four parts: llm, platform, quota and balance.

Part B: calling the API

B1. Evren models

Evren models carry the EV/ prefix. Every call uses your Evren key and your Evren account’s credits:

curl -s $GW/v1/models -H "Authorization: Bearer $BOSPHORUS_KEY" | jq -r '.data[].id' | grep '^EV/'

curl -s $GW/v1/chat/completions -H "Authorization: Bearer $BOSPHORUS_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"EV/deepseek-v4-flash","messages":[{"role":"user","content":"Merhaba"}]}' \
  | jq -r '.choices[0].message.content'

curl -s $GW/v1/embeddings -H "Authorization: Bearer $BOSPHORUS_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"EV/qwen3-embedding-8b","input":"Merhaba dünya"}' | jq '.data[0].embedding | length'

On the day this was written the chat answered Merhaba! Size nasıl yardımcı olabilirim? and the embedding had 4096 dimensions. Each answer’s usage also carries an evren block with the credits Evren held and has left, and the model it routed to.

The same works from any OpenAI SDK; only the address and the key change:

import os
from openai import OpenAI

client = OpenAI(base_url="https://ai.corp.example/v1", api_key=os.environ["BOSPHORUS_KEY"])
reply = client.chat.completions.create(
    model="EV/deepseek-v4-flash",
    messages=[{"role": "user", "content": "Merhaba"}],
)
print(reply.choices[0].message.content)

The Evren models on the day this was written:

Model Serves
EV/auto Chat; Evren picks the model
EV/deepseek-v4-flash, EV/deepseek-v4.1-flash, EV/gemma-4-31b, EV/glm-5.3, EV/mimo-v2.6-pro, EV/qwen3.8-flash-next Chat
EV/qwen3-vl-30b Chat with images
EV/qwen3-embedding-8b Embeddings

/v1/models always shows the current list for you.

B2. A tool server over plain HTTP

One tool call is one POST: the tool’s arguments are the JSON body, and the gateway adds your value from your vault on the way to the server. This searches O’Reilly with your own token:

curl -s -X POST $GW/api/mcp/oreilly/tools/search_oreilly_content \
  -H "Authorization: Bearer $BOSPHORUS_KEY" -H 'Content-Type: application/json' \
  -d '{"query":"kubernetes networking"}' | jq '{isError, result: (.result | .[0:200])}'

The answer is {"result": "…", "isError": false}. To see a server’s tools and their arguments, read its description with the same key:

curl -s $GW/api/mcp/oreilly/openapi.json -H "Authorization: Bearer $BOSPHORUS_KEY" | jq '.paths | keys'

For O’Reilly it lists one path, /tools/search_oreilly_content.

B3. A tool server from an MCP client

MCP clients such as Claude Code use the relay address and the same key. No tool token goes into the file:

"oreilly": {
  "type": "http",
  "url": "https://ai.corp.example/api/mcp/oreilly",
  "headers": {
    "Authorization": "Bearer ${BOSPHORUS_KEY}"
  }
}

In aimo for VS Code there is nothing to configure: once you are signed in, it reaches the same servers the same way.

Which credential to send

You send What happens
Your personal platform key, gpk_… Use this. The gateway knows it is you and reads your vault.
Your sign-in token Works for about an hour, if you already have a personal key. Good for a quick test.
A team or service key EV/ models answer 503 because there is no person to read a key for, and tool servers that need a person answer 401.
Your Evren key or a tool token itself 401 invalid api key. Those keys belong on My variables, never in a request.

What the platform promises about your keys

When something is not right

What you see What to do
503 “EV/…” is served with YOUR OWN Evren key and you have not registered one Save your Evren LLM key on My variables (A2).
503 … this request carries no user identity to look one up for You sent a team or service key. Use your personal key (A1).
401 this mcp server requires a user identity (per-user key or signed user context) The same, for a tool server.
A tool answer with "isError": true: This tool needs your own OREILLY_MCP_TOKEN … That value is not in your vault. The message links to the right place on My variables.
… could not be read from the vault just now, so the tool was not called The vault is briefly unreachable. Try again in a minute; if it persists, tell your administrator.
401 invalid api key The key was revoked or mistyped. Mint it again with ?client=api&rotate=true.
400 from EV/glm-5.3 That model rejects the min_p and logit_bias sampling settings. Leave them out.