Introduction
Vantafold is a single API in front of every model your product might use. You send a
request to api.vantafold.ai; we normalise it, pick a model according to your
policy, call the provider, and return one response shape with the cost and the route attached.
If you have used a provider SDK before, the mental model is the same. The differences are that the model name is a string you can change freely, and that every response tells you what it cost.
New here? The fastest path is to install an SDK, export a key, and run the snippet under Your first call. It takes about two minutes.
Getting started
Install the SDK for your language. Every client is generated from the same OpenAPI spec, so the method names and field names match across languages.
pip install vantafold
npm install @vantafold/sdk
go get github.com/vantafold/vantafold-go
gem install vantafold
Requirements
- Python 3.9+, Node 18+, Go 1.21+, or Ruby 3.1+.
- Outbound HTTPS to
api.vantafold.aion port 443. - An API key from the dashboard — the free tier needs no card.
Authentication
Vantafold uses bearer tokens. Create a key per environment, never per developer, and scope it to a project so its spend is capped independently.
export VANTAFOLD_API_KEY="vf_live_8f2c41a9b7e04d31"
Every SDK reads VANTAFOLD_API_KEY from the environment by default, so the
client constructor usually takes no arguments. Pass the key explicitly only when you manage
several credentials in one process.
Key types
- Live keys (
vf_live_…) bill against your plan and route to real models. - Test keys (
vf_test_…) return deterministic fixtures, cost nothing, and are safe in CI. - Restricted keys can be limited to specific models, endpoints, or a monthly spend ceiling.
Never ship a key to a browser or a mobile app. Call Vantafold from your
server. If you need a client-side path, mint a short-lived scoped token with
POST /v1/tokens and hand that out instead.
Making your first call
The reason endpoint is the one you will use most. It takes an input, an optional
model, and returns text, tool calls, or structured output.
from vantafold import Vantafold
client = Vantafold() # reads VANTAFOLD_API_KEY from the environment
response = client.reason(
model="auto",
input="Summarise this support thread in three bullets.",
metadata={"project": "support-triage"},
)
print(response.output_text)
print(response.route.selected, response.usage.cost_usd)
import { Vantafold } from "@vantafold/sdk";
const client = new Vantafold(); // reads VANTAFOLD_API_KEY
const response = await client.reason({
model: "auto",
input: "Summarise this support thread in three bullets.",
metadata: { project: "support-triage" },
});
console.log(response.output_text);
console.log(response.route.selected, response.usage.cost_usd);
curl https://api.vantafold.ai/v1/reason \
-H "Authorization: Bearer $VANTAFOLD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"input": "Summarise this support thread in three bullets.",
"metadata": { "project": "support-triage" }
}'
A successful response looks like this. Note route and usage — they
are on every response, whichever model answered.
{
"id": "req_8f2c41a9",
"model": "frontier-sm",
"output_text": "- Customer cannot log in after SSO migration\n- Error is 403 from the IdP\n- Escalated to platform on 12 Aug",
"usage": { "input_tokens": 1840, "output_tokens": 64, "cost_usd": 0.0021 },
"route": { "requested": "auto", "selected": "frontier-sm", "attempts": 1,
"reason": "met quality bar at 14% of frontier-lg cost" },
"trace_id": "tr_5b1d9e0c"
}
Choosing a model
Pass model="auto" to let the router choose, or name a model from the
catalog to pin it. Pinning is the right default while you are
still evaluating; auto is the right default once you have an evaluation set.
Streaming
Every model streams, in one event format. Deltas arrive as
output_text.delta; tool calls and completion arrive as their own events.
stream = client.reason.stream(model="auto", input=prompt)
for event in stream:
if event.type == "output_text.delta":
print(event.delta, end="", flush=True)
elif event.type == "tool_call":
print(f"\n[tool] {event.name}({event.arguments})")
elif event.type == "response.completed":
print(f"\n[done] {event.usage.cost_usd:.4f} USD via {event.route.selected}")
Errors and retries
The SDKs retry idempotent failures with exponential backoff and jitter. What reaches your code is a failure that survived the whole fallback chain.
from vantafold import Vantafold, RateLimitError, ProviderError
client = Vantafold(max_retries=3, timeout=30.0)
try:
response = client.reason(model="auto", input=prompt)
except RateLimitError as err:
# Your project spend cap or a provider limit. err.retry_after is seconds.
schedule_retry(after=err.retry_after)
except ProviderError as err:
# Every fallback in the chain failed. err.attempts lists what was tried.
log.warning("all routes failed", attempts=err.attempts)
Status codes
| Code | Meaning | What to do |
|---|---|---|
| 400 | Malformed request | Fix the payload. The message names the offending field. |
| 401 | Bad or missing key | Check the Authorization header and the key's environment. |
| 403 | Key not permitted | The key is restricted from this model or endpoint. |
| 404 | Unknown model | Check the model string against the catalog. |
| 422 | Schema violation | Structured output failed validation after one retry. |
| 429 | Rate or spend limit | Back off for retry_after seconds, or raise the cap. |
| 500 | Vantafold error | Retry. If it persists, check the status page. |
| 529 | All routes degraded | Every fallback failed. attempts lists what was tried. |