layahost
Menu · Migrate from Jev

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:

Environment
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.

Jev SDK on layahost
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)
Jev SDK on layahost
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.

Tested with 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/systemone and GET /v1/models, with no /api prefix.
  • The request body: state, model and a questions map with noul, choice and score questions. instructions is optional, as in Jev.
  • The answer fields: choice and probabilities; noul; score, legend and probabilities; plus usage.
  • Model names: jev-latest, the SDKs' default, and any other jev-* name are accepted and answered by laya-auto.
  • Request IDs: every response has an x-typesafe-request-id header, so response.request_id in Python and requestId in JavaScript work as usual. The same ID is in x-request-id, in meta.request_id and in Logs.
  • Errors: {"detail": {"error_type": ..., "message": ...}}, and FastAPI-style lists for 422. The SDKs raise their usual exception classes, and their automatic retries on 429 and 5xx honour our retry-after header.

What is different

AreaOn 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:

Request ID and meta
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
Request ID and meta
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.

lang and cache
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)
lang and cache
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.