Developer platform

Build on Vela credits

One OpenAI-compatible API for 400+ models, paid from credits your tokenized stocks earn. Plug it into your code, your agent over MCP, or let your users sign in with Vela and spend their own credits.

Quick start

  1. Open the app and sign in with your wallet.
  2. Make sure you have credits. Deposit into a vault to earn them, or buy them with a card.
  3. Go to Developers, then Create key. Copy the key; it's shown once.
  4. Point any OpenAI SDK at https://velastocks.online/api/v1 with your key.
from openai import OpenAI

client = OpenAI(
    base_url="https://velastocks.online/api/v1",
    api_key="YOUR_VELA_KEY",
)

reply = client.chat.completions.create(
    model="openai/gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello"}],
)
print(reply.choices[0].message.content)
Base URL: https://velastocks.online/api/v1. The API has its own host, separate from this website. Opening the base URL in a browser shows a short guide; requests go to paths under it, like /v1/models and /v1/chat/completions.

Anything that speaks the OpenAI chat format works the same way: LangChain, the Vercel AI SDK, LlamaIndex, Cursor-style tools that take a custom base URL, and so on.

API keys

Create keys in the app under Developers. Give each app or environment its own key so you can see what each one spends and shut one off without touching the others.

SettingWhat it does
NameA label for you, like "Discord bot" or "staging". It shows in the activity log.
Spending limitOptional. Once the key has spent this much in credits, it's turned away with key_limit_reached until you raise or remove the limit. It's checked before each request, so a final request can finish slightly past it.
Allowed modelsOptional. A list of model ids the key may use, such as openai/gpt-4o-mini or vela/auto. Anything else returns model_not_allowed.
PauseTurns the key off right away without deleting it. Resume it any time.
DeleteRevokes the key for good.

Each wallet can have up to 20 keys. Keys are stored only as hashes, so we can't show one again. If you lose a key, delete it and make another.

API keys can call models but can't manage your account, create other keys, or buy credits. Keep them on your server, never in a browser or app bundle.

Models

Use any model id from the list endpoint. It returns 400+ models from OpenAI, Anthropic, Google, Meta, DeepSeek, Mistral and more, with their per-token prices.

curl https://velastocks.online/api/v1/models

Auto routing

Set model to vela/auto and our routing engine picks the cheapest model that can handle each request: quick questions go to a fast model, code to a stronger one, and hard reasoning to the top tier. That's how credits go up to 2–3x further.

Auto routing is for wallets holding at least 1,000 $VELA. The response tells you what was picked in the x-vela-model and x-vela-tier headers. To make auto start from a stronger tier, send x-route-floor: mid or top.

Requests

POST /v1/chat/completions takes the standard OpenAI body. Streaming ("stream": true), tools, JSON mode, images and other provider options pass straight through to the model.

Response headers

HeaderMeaning
x-vela-modelThe model that answered.
x-vela-tierfast, mid or top. Only when auto routing chose the model.
x-vela-costWhat this request took from your credits, in dollars. Non-streaming requests only; streamed requests show their cost in the activity log.

Who am I

GET /v1/me returns what the key can still spend (available_usd), plus its name and limit. Called with a Sign in with Vela token, it returns the user's user_id for your app instead of their wallet.

SDKs

The OpenAI SDKs above work as they are. If you'd rather have something smaller, our clients for JavaScript and Python have no dependencies, and they include helpers for Sign in with Vela. Download one file and drop it into your project:

import { Vela } from "./vela.mjs";

const vela = new Vela({ apiKey: process.env.VELA_API_KEY });

console.log(await vela.ask("Explain Morpho in one line", { model: "openai/gpt-4o-mini" }));
console.log(vela.last);            // { model, tier, costUsd }

for await (const t of vela.stream({ messages: [{ role: "user", content: "Count to 5" }] }))
  process.stdout.write(t);

const me = await vela.me();        // { available_usd, ... }

Both raise VelaError with status and type from the error table. The JavaScript client runs in Node 18+, Deno, Bun and browsers; the Python one needs 3.8+.

Agents (MCP)

Vela runs a remote MCP server, so Claude, Cursor and other agents can call any model with your credits: for a second opinion, to hand off to a cheaper model, or to reach one they don't have.

SettingValue
URLhttps://velastocks.online/api/mcp
TransportStreamable HTTP
AuthHeader Authorization: Bearer YOUR_VELA_KEY
claude mcp add --transport http vela https://velastocks.online/api/mcp \
  --header "Authorization: Bearer YOUR_VELA_KEY"

Tools

ToolWhat it does
ask_modelSends a prompt (and optional system message) to a model and returns the reply, with the model used and what it cost. Leave model empty or use vela/auto for auto routing.
list_modelsSearches models by name, with prices per million tokens.
get_balanceHow many credits the key can still spend.
Give your agent its own key with a spending limit. Every call it makes shows up in your activity log under that key's name.

Sign in with Vela

Add a "Sign in with Vela" button to your app. Your users approve it once with their wallet, choose how much your app may spend, and from then on your app calls models with their credits. You never handle API keys or payments for them.

It's standard OAuth 2.0 (authorization code with PKCE), so most OAuth libraries work.

  1. In the app, go to Developers → Sign in with Vela → Create an app. Add your redirect URL. Server apps get a client secret; browser and mobile apps use PKCE only.
  2. Send the user to https://velastocks.online/authorize with response_type=code, client_id, redirect_uri, state, code_challenge and code_challenge_method=S256.
  3. They come back to your redirect URL with ?code=…&state=…. Check that state matches.
  4. Swap the code at POST https://velastocks.online/api/oauth/token for an access token, then use it exactly like an API key.
import { Vela, createPkce, authorizeUrl, exchangeCode } from "./vela.mjs";

app.get("/login", async (req, res) => {
  const { verifier, challenge } = await createPkce();
  req.session.verifier = verifier;
  req.session.state = crypto.randomUUID();
  res.redirect(authorizeUrl({ clientId: CLIENT_ID, redirectUri: REDIRECT_URI, state: req.session.state, codeChallenge: challenge }));
});

app.get("/callback", async (req, res) => {
  if (req.query.state !== req.session.state) return res.status(400).send("Bad state");
  if (req.query.error) return res.send("Sign-in cancelled");
  const t = await exchangeCode({ clientId: CLIENT_ID, clientSecret: CLIENT_SECRET, code: req.query.code,
                                 codeVerifier: req.session.verifier, redirectUri: REDIRECT_URI });
  req.session.vela = t.access_token;   // keep it server-side
  const vela = new Vela({ apiKey: t.access_token });
  res.send(await vela.ask("Write a welcome line for " + t.user_id));
});

What your app gets

  • An access token that works on /v1/chat/completions, /v1/models, /v1/me and the MCP server, up to the limit the user chose.
  • A user_id that stays the same for that user in your app. It's different in every app, and apps never see the user's wallet address.

What users control

  • They set your app's spending limit when they sign in, and can change it later.
  • They can disconnect your app any time under Developers → Connected apps. The token stops working at once.
  • Signing in again replaces the old token.

Rules

  • PKCE with S256 is required for every app. Redirect URLs must match exactly and use https:// (or http://localhost while testing).
  • Codes last 10 minutes and work once. If a code is used twice, the token it produced is revoked.
  • Keep client secrets and access tokens on your server. Deleting an app signs every user out of it.
  • Token errors use OAuth's shape: {"error": "invalid_grant", "error_description": "…"}.

Billing

Every request is paid from your Vela credit balance. You're charged for the tokens the model actually used, at the provider's price plus Vela's service fee. Every charge shows up in Developers → Activity, with tokens in and out, cost, time taken, and which key made it.

Credits come from two places: interest your vault deposits earn, and credits you buy with a card. When your balance runs out, requests return insufficient_balance until you top up.

Errors

Errors use the OpenAI shape, {"error": {"message", "type", "code"}}, so existing SDK error handling keeps working. Check type to tell them apart.

StatusTypeWhat to do
401authentication_errorThe key is wrong or was deleted.
401key_disabledThe key is paused. Resume it in the app.
402insufficient_balanceOut of credits. Deposit or buy more.
402key_limit_reachedThis key hit its spending limit. Raise or remove it.
403model_not_allowedThe key isn't allowed to use that model.
403auto_routing_lockedAuto routing needs 1,000 $VELA in the key's wallet. Name a model instead.
429rate_limit_errorToo many requests. Back off and retry.
502upstream_errorThe model provider didn't answer. Retry, or try another model. You aren't charged.

Rate limits

Each wallet can make up to 120 requests a minute across all its keys. Need more? Reach out on X at @VelaStocks.