Migrate from Jev
layahost implements POST /v1/systemone and GET /v1/models with the same requests, responses and errors as TypeSafe AI's Jev API. Existing code keeps working after you change two settings: the base URL and the API key.
1. Create a layahost key
Sign up, add credit on the Billing page, and create a key on the API keys page. See Authentication.
2. Point your client at layahost
Both official SDKs, typesafe-sdk for Python and @typesafe-ai/sdk for JavaScript, read their configuration from the same environment variables. Set them and run your code unchanged:
export TYPESAFE_BASE_URL=https://layahost.com
export TYPESAFE_API_KEY=lh_...
Or pass the same settings to the client constructor: base_url in Python, baseURL in JavaScript.
import os
from typesafe_sdk import Choice, TypeSafeClient
with TypeSafeClient(
base_url="https://layahost.com",
api_key=os.environ["LAYAHOST_API_KEY"],
) as client:
response = client.system_one(
state={"document": "I was charged twice. Please fix this ASAP."},
questions={
"category": Choice(
instructions="What is this ticket about?",
criteria={"billing": None, "technical": None, "other": None},
),
},
)
print(response.choices["category"].choice)
import { choice, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient({
baseURL: "https://layahost.com",
apiKey: process.env.LAYAHOST_API_KEY,
});
const response = await client.systemOne({
state: { document: "I was charged twice. Please fix this ASAP." },
questions: {
category: choice("What is this ticket about?", {
billing: null,
technical: null,
other: null,
}),
},
});
console.log(response.answers.category.choice);
If you call the HTTP API directly, replace https://api.typesafe.ai with https://layahost.com. The paths stay the same.
typesafe-sdk 0.7.1 for Python and @typesafe-ai/sdk 0.6.0 for JavaScript: system_one / systemOne with all three question types, models.list(), request IDs, and the SDKs' authentication and validation errors.3. Check your thresholds
layahost answers with Laya, a different model from Jev. Answers have the same shape, but the probabilities will not match what Jev returned. If your code compares a probability or noul value with a threshold, re-check that threshold on a sample of your own data before you switch production traffic.
What stays the same
- Paths:
POST /v1/systemoneandGET /v1/models, with no/apiprefix. - The request body:
state,modeland aquestionsmap withnoul,choiceandscorequestions.instructionsis optional, as in Jev. - The answer fields:
choiceandprobabilities;noul;score,legendandprobabilities; plususage. - Model names:
jev-latest, the SDKs' default, and any otherjev-*name are accepted and answered bylaya-auto. - Request IDs: every response has an
x-typesafe-request-idheader, soresponse.request_idin Python andrequestIdin JavaScript work as usual. The same ID is inx-request-id, inmeta.request_idand in Logs. - Errors:
{"detail": {"error_type": ..., "message": ...}}, and FastAPI-style lists for422. The SDKs raise their usual exception classes, and their automatic retries on429and5xxhonour ourretry-afterheader.
What is different
| Area | On layahost |
|---|---|
Response model |
Names the Laya checkpoint that answered, laya-english or laya-multilingual, even when you ask for jev-latest. Update any code that checks this field. See Models. |
| Extra response fields | A meta object (checkpoint, cache hit, latency, request ID, decisions, and the cost as cost_micros and cost_usd), and confidence on yes/no answers. The SDKs ignore fields they don't know. |
| Extra request fields | lang (a language hint) and cache (default true). Both are optional. See POST /v1/systemone. |
usage.output_tokens |
Always 0: Laya picks between your options and generates no text. |
| Limits | Up to 32 questions per request, 32,000 characters of state and 2 to 10 levels per score question. Jev allows up to 255 options per choice question; on layahost all option names and descriptions of one question must fit in 192 tokens, roughly 100 to 150 short options, or you get 422. The rate limit is 600 requests per minute per key. |
| Billing | Prepaid credit at $5 per million decisions, where one decision is one answered question. An empty balance returns 402 with error_type insufficient_credits. See Pricing & billing. |
Read request IDs and meta with the SDKs
The SDKs' own request-ID accessors work, on responses and on errors (request_id in Python, requestId in JavaScript). Quote the ID when you contact support. The meta object is a layahost extension that the SDKs don't model, but you can read it from the raw response:
from typesafe_sdk import Noul, TypeSafeClient
with TypeSafeClient() as client:
response = client.system_one(
state="Where is my parcel? It was due on Monday.",
questions={"shipping": Noul(instructions="Is this about a delivery?")},
)
print(response.request_id)
print(response.raw_http_response.json()["meta"]) # layahost extension
import { noul, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient();
const { data, requestId } = await client
.systemOne({
state: "Where is my parcel? It was due on Monday.",
questions: { shipping: noul("Is this about a delivery?") },
})
.withResponse();
console.log(requestId);
console.log(Reflect.get(data, "meta")); // layahost extension, not in the SDK's types
Send layahost extensions
Pass lang or cache through the SDKs like this. In Python, use extra_body. In JavaScript, extra properties on the request object are forwarded as they are; build the request as a variable so TypeScript accepts the extra fields.
from typesafe_sdk import Noul, TypeSafeClient
with TypeSafeClient() as client:
response = client.system_one(
model="laya-auto",
state="Ich möchte mein Abo kündigen.",
questions={"cancel": Noul(instructions="Does the customer want to cancel?")},
extra_body={"lang": "de", "cache": False},
)
print(response.nouls["cancel"].noul)
import { noul, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient();
const request = {
model: "laya-auto",
state: "Ich möchte mein Abo kündigen.",
questions: { cancel: noul("Does the customer want to cancel?") },
lang: "de",
cache: false,
};
const response = await client.systemOne(request);
console.log(response.answers.cancel.noul);
Handle a low balance
The Jev SDKs have no special class for 402. Python raises TypeSafeAPIError and JavaScript throws APIError, both with status set to 402. Don't retry these: top up instead. We also email you when your balance runs low; set the threshold in Settings → Data & alerts. See Errors.