VaultEdge API

Call your trained models from your own code. One API key, one HTTP request, a prediction back. Everything below works against the live API — there is no separate sandbox and no SDK to install.

Base URL https://api.vaultedge.dev

Getting started

Three steps. If you have a trained model already, this takes about two minutes.

1

Create an API key

Sign in and open API Tokens, or click Share on any trained model and create one there.

The key is shown once, when you create it. We store only a hash of it, so it cannot be shown again — copy it before you close the dialog. Lost a key? Revoke it and create another.

2

Send it on every request

The key goes in a header called X-Api-Key. Not a query string, not a bearer token — just that header:

Header
X-Api-Key: YOUR_API_TOKEN

That is the whole of authentication. The key identifies you, your subscription and which models you may call, so nothing else in the request decides who you are.

3

Make your first call

Replace YOUR_API_TOKEN with your key and 123 with your model id, then paste this into a terminal:

curl -X POST "https://api.vaultedge.dev/predict" \
  -H "X-Api-Key: YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"trainingTypeId": 123, "inputs": {"YourColumn": "value", "AnotherColumn": "42"}}'
const response = await fetch("https://api.vaultedge.dev/predict", {
  method: "POST",
  headers: {
    "X-Api-Key": "YOUR_API_TOKEN",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    trainingTypeId: 123,
    inputs: { YourColumn: "value", AnotherColumn: "42" }
  })
});

const result = await response.json();
console.log(result.predictedLabel, result.probability);
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Api-Key", "YOUR_API_TOKEN");

var response = await client.PostAsJsonAsync("https://api.vaultedge.dev/predict", new
{
    trainingTypeId = 123,
    inputs = new Dictionary<string, string>
    {
        ["YourColumn"] = "value",
        ["AnotherColumn"] = "42"
    }
});

Console.WriteLine(await response.Content.ReadAsStringAsync());

A 200 with "success": true means you are done — everything after this page is detail.

Authentication

Every endpoint on this page takes the same header. A request without it, or with a revoked or mistyped key, gets 401 and nothing else — the API does not say which of those it was.

Header
X-Api-Key: YOUR_API_TOKEN

What a key can do

A key belongs to one subscription and acts as the user who created it. It can call the models that subscription owns, and its usage counts against that subscription's plan. Keys come in two kinds:

  • API keys — for your own server-side code. They reach every model in the subscription.
  • Widget keys — for the chat widget on your public site. A widget key is bound to one model and to the web origins you list, and it cannot be used for anything else. See Adding the chat widget.

Never put an API key in a web page, a mobile app or any public repository. Anything a browser downloads, a visitor can read. Call the API from your own server, and use a widget key — which is origin-locked and model-locked — for anything that runs in a browser. If a key leaks, revoke it on the API Tokens screen; revocation takes effect on the next request.

Finding your model id

Every request names the model to use, as trainingTypeId. Open the model and click Share — the ready-made samples there already have your id filled in, so you can copy one and change only the key.

A model you have retired keeps its id but stops answering: those calls get 410 Gone rather than a 404, because the model did exist and its owner withdrew it on purpose. See Errors.

POST /predict

A prediction from a tabular model — the kind trained on a spreadsheet or a CSV. You send the column values, you get the answer.

Request

FieldTypeNotes
trainingTypeId number Required. Which model to use.
inputs object Required. Values keyed by your own column names — the ones in the file you trained on, spelled the same way. Values are sent as strings; numbers are parsed for you.
curl -X POST "https://api.vaultedge.dev/predict" \
  -H "X-Api-Key: YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"trainingTypeId": 123, "inputs": {"YourColumn": "value", "AnotherColumn": "42"}}'
const response = await fetch("https://api.vaultedge.dev/predict", {
  method: "POST",
  headers: {
    "X-Api-Key": "YOUR_API_TOKEN",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    trainingTypeId: 123,
    inputs: { YourColumn: "value", AnotherColumn: "42" }
  })
});

const result = await response.json();
console.log(result.predictedLabel, result.probability);
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Api-Key", "YOUR_API_TOKEN");

var response = await client.PostAsJsonAsync("https://api.vaultedge.dev/predict", new
{
    trainingTypeId = 123,
    inputs = new Dictionary<string, string>
    {
        ["YourColumn"] = "value",
        ["AnotherColumn"] = "42"
    }
});

Console.WriteLine(await response.Content.ReadAsStringAsync());

Response

200 OK
{
  "success": true,
  "predictedLabel": "Likely to renew",
  "probability": 0.87,
  "score": null,
  "scores": [0.13, 0.87],
  "message": null,
  "trainingModelId": 4412,
  "trainingId": 903,
  "trainingTypeId": 123
}

Which fields are filled depends on what the model predicts: a category model answers with predictedLabel and probability, a numeric one with score. See Responses.

POST /predict/text

Classify a piece of text with a text model — sorting a message, a review or a support ticket into one of the categories you trained on.

Request

FieldTypeNotes
trainingTypeIdnumberRequired.
text string Required. The text to classify, as one string.
curl
curl -X POST "https://api.vaultedge.dev/predict/text" \
  -H "X-Api-Key: YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"trainingTypeId": 123, "text": "The delivery arrived two days late and the box was damaged."}'

Response

The same shape as /predict: predictedLabel with the winning category and probability with its confidence.

POST /predict/image

Classify a picture. This endpoint takes multipart/form-data rather than JSON, so the file travels as bytes instead of growing by a third as base64.

Request

Form fieldTypeNotes
trainingTypeIdtextRequired.
imagefileRequired. The picture to classify.
curl -X POST "https://api.vaultedge.dev/predict/image" \
  -H "X-Api-Key: YOUR_API_TOKEN" \
  -F "trainingTypeId=123" \
  -F "image=@/path/to/photo.jpg"
const form = new FormData();
form.append("trainingTypeId", "123");
form.append("image", fileInput.files[0]);

const response = await fetch("https://api.vaultedge.dev/predict/image", {
  method: "POST",
  headers: { "X-Api-Key": "YOUR_API_TOKEN" },
  body: form
});

console.log(await response.json());
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Api-Key", "YOUR_API_TOKEN");

using var form = new MultipartFormDataContent
{
    { new StringContent("123"), "trainingTypeId" },
    { new ByteArrayContent(File.ReadAllBytes("photo.jpg")), "image", "photo.jpg" }
};

var response = await client.PostAsync("https://api.vaultedge.dev/predict/image", form);

Console.WriteLine(await response.Content.ReadAsStringAsync());

POST /predict/image/batch

Classify up to 16 pictures for one model in a single request. The same form as /predict/image, with the field images repeated once per file. Faster than one request per picture, and it counts as one call against the rate limit.

Request

Form fieldTypeNotes
trainingTypeIdtextRequired.
images file, repeated Required. At most 16 files and 8 MB together.

Response

An array of response objects, one per file and in the order you sent them. Each succeeds or fails on its own: a file that is not a picture fails alone, and when your plan has fewer predictions left than you sent, the first ones are answered and the rest carry the quota message. Only the answered ones are counted.

curl -X POST "https://api.vaultedge.dev/predict/image/batch" \
  -H "X-Api-Key: YOUR_API_TOKEN" \
  -F "trainingTypeId=123" \
  -F "images=@/path/to/first.jpg" \
  -F "images=@/path/to/second.jpg"

POST /chat

Ask the model a question in plain language instead of building the inputs object yourself. This is the endpoint behind the chat widget, and it needs an AI Brain connected to the model.

The AI Brain runs the conversation, not the prediction. It is told the model's description and the names of its input fields, so it knows what to ask for. Your training data is never sent to it, and the answer still comes from the model you trained.

Request

FieldTypeNotes
trainingTypeIdnumberRequired.
messagestringRequired. What the person asked.
history array Optional. Earlier turns, each { "role": "user" | "assistant", "content": "…" }. Send it back on every turn to keep the thread; the API stores no conversation of its own.
curl -X POST "https://api.vaultedge.dev/chat" \
  -H "X-Api-Key: YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"trainingTypeId": 123, "message": "How many sales last month?"}'
const response = await fetch("https://api.vaultedge.dev/chat", {
  method: "POST",
  headers: {
    "X-Api-Key": "YOUR_API_TOKEN",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    trainingTypeId: 123,
    message: "How many sales last month?"
  })
});

console.log((await response.json()).reply);
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Api-Key", "YOUR_API_TOKEN");

var response = await client.PostAsJsonAsync("https://api.vaultedge.dev/chat", new
{
    trainingTypeId = 123,
    message = "How many sales last month?"
});

Console.WriteLine(await response.Content.ReadAsStringAsync());
import requests

response = requests.post(
    "https://api.vaultedge.dev/chat",
    headers={"X-Api-Key": "YOUR_API_TOKEN"},
    json={"trainingTypeId": 123, "message": "How many sales last month?"},
)

print(response.json()["reply"])

Response

200 OK
{
  "success": true,
  "reply": "About 2 days for standard delivery to San Francisco",
  "usedModel": true,
  "interpretedInputs": {
    "Destination": "San Francisco",
    "ShippingMethod": "Standard"
  },
  "missingInputs": null,
  "prediction": {
    "success": true,
    "score": 2.1,
    "predictedLabel": null,
    "probability": null
  }
}
FieldNotes
replyWhat to show the person.
usedModel true when the answer came from a prediction. When it is false the Brain was still gathering details and no prediction was spent.
missingInputs Fields it still needs before it can predict. Useful if you are building your own chat UI and want to ask for them directly.
interpretedInputsWhat it understood from the conversation.
predictionThe full prediction object, when there was one.

POST /chat/image

The same conversation, for an image model: the person sends a picture and asks about it. Takes multipart/form-data, with the message and the file as form fields.

GET /llm/providers

Which AI providers your subscription can use for chat. Worth calling only if you are building your own interface and want to show the choice.

curl
curl "https://api.vaultedge.dev/llm/providers" \
  -H "X-Api-Key: YOUR_API_TOKEN"

Responses

Every prediction endpoint answers with the same object. Fields that do not apply to your kind of model are null rather than absent.

FieldTypeNotes
success boolean Check this first. A 200 can still carry false.
predictedLabelstringThe winning category, for a classifier.
probabilitynumberConfidence in that category, 0 to 1.
scorenumberThe predicted value, for a numeric model.
scoresnumber[]The score for every category, in the model's own order.
messagestringWhy it failed, when it did. Safe to show a developer, not an end user.
trainingModelId, trainingId, trainingTypeId number Which model version answered. Worth logging: it is how you tell later which version produced a given answer.

Errors

The status code tells you whether retrying can ever work. That distinction is deliberate — treat 403 and 429 differently or you will build a client that retries forever.

StatusMeaningWhat to do
400 The request is malformed — no model id, or inputs the model does not recognise. Fix the request. Retrying it unchanged will fail again.
401 Missing, mistyped or revoked key. Check the X-Api-Key header.
403 The key is valid but not allowed this call — another subscription's model, or a widget key used off its model or its origin. Do not retry. Waiting does not change it.
410 The training was retired by its owner. It existed; it no longer answers. Ask the owner, or point at a current model. Not a client bug.
429 Too many requests in a minute, or the plan's monthly allowance is spent. Retry with a backoff. This one succeeds again later.
503 Inference is temporarily unavailable. Retry with a backoff.

Rate limits and quotas

There are two separate ceilings, and they fail the same way but mean different things.

  • Rate limit — how many calls you may make in one minute, counted in a fixed window, with separate allowances for prediction and chat. It protects the service from a burst, and it resets within the minute.
  • Plan allowance — how many predictions and chat messages your subscription includes per month. This resets when the month does. Your current usage is on the Statistics screen.

Both answer 429, and the message field says which one you hit. A prediction is counted only when it succeeds — a refused or failed call costs you nothing.

Adding the chat widget

The widget puts your model on your own website as a chat panel, so visitors can ask it questions without you writing any code. It is one script tag.

1

Create a widget key

Open the model, click Share, and create a widget key — not an API key. A widget key is safe to put in a public page: it works for that one model only, and only on the websites you list.

2

List the websites that may use it

Add every origin the widget will run on. An origin is the scheme, host and port with no path and no trailing slash:

Allowed origins
https://example.com
https://www.example.com

This is the mistake that costs people an afternoon. https://example.com and https://www.example.com are different origins — list both if you serve both. An origin that is not listed gets 403 and the panel stays empty.

3

Paste the script into your page

Anywhere in the HTML — it is defer, so it will not slow the page down. A floating chat button appears in the corner:

HTML
<script src="https://vaultedge.dev/js/widget.js"
        data-key="YOUR_WIDGET_KEY"
        data-title="Ask about our products"
        defer></script>

To place the panel inside your own layout instead of floating it, give it an element to fill:

HTML — inline
<div id="chat-panel" style="height: 560px"></div>

<script src="https://vaultedge.dev/js/widget.js"
        data-key="YOUR_WIDGET_KEY"
        data-title="Ask about our products"
        data-mode="inline"
        data-target="#chat-panel"
        defer></script>

Widget options

Everything except data-key has a sensible default.

AttributeNotes
data-keyRequired. Your widget key.
data-titleThe heading on the panel. Shown to your visitors, so name it for them.
data-modeinline to place the panel in your page. Floating by default.
data-targetA CSS selector for the element to fill. Needed with data-mode="inline".
data-imagetrue for an image model, so the panel offers a file picker.
data-positionWhich corner the floating button sits in.
data-opentrue to open the panel on load instead of waiting for a click.

The widget key never reaches your visitors' conversations with your data. Each visit exchanges the key for a short-lived session bound to that one model, which is why a copied key is useless on a site you have not listed.

Stuck?

Email [email protected] with the endpoint you called, the status code you got back and the message field. That is almost always enough to answer in one reply.

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please reload the page.