Skip to content
Docs

TypeSafe API with AI Gateway

Keep using the TypeSafe SDK and route requests through AI Gateway by changing one setting.

Requests are billed through AI Gateway and appear in your usage and observability alongside every other model you call.

If you are writing new code instead of migrating, use the Decision API. It is the same capability without TypeSafe-specific naming.

The TypeSafe-compatible API is available at the following base URL:

https://ai-gateway.vercel.sh/typesafe

The TypeSafe-compatible API supports the same authentication methods as the main AI Gateway:

  • API key: Use your AI Gateway API key with the Authorization: Bearer <token> header
  • OIDC token: Use your Vercel OIDC token with the Authorization: Bearer <token> header

You only need one of these. This is the credential AI Gateway authenticates you with, not the credential used to call the model.

To bill the provider directly instead of through AI Gateway, add a TypeSafe key under BYOK.

Change the base URL and the API key:

client.ts
  import { TypeSafeClient } from '@typesafe-ai/sdk';
 
  const client = new TypeSafeClient({
-   apiKey: process.env.TYPESAFE_API_KEY,
+   apiKey: process.env.AI_GATEWAY_API_KEY,
+   baseURL: 'https://ai-gateway.vercel.sh/typesafe',
  });

Everything else stays the same:

triage.ts
const result = await client.systemOne({
  state: 'I was charged twice for my subscription.',
  questions: {
    refund: { type: 'noul', instructions: 'Is the customer asking for money back?' },
    department: {
      type: 'choice',
      instructions: 'Which team should handle this?',
      criteria: { billing: 'Charges and refunds', technical: 'Bugs and outages' },
    },
  },
});
 
console.log(result.answers.refund); // { type: 'noul', noul: 0.98 }
  • POST /typesafe/v1/systemone answers typed questions about state
  • GET /typesafe/v1/models lists the decision models available to you

This API implements the TypeSafe request and response shapes.

systemone.sh
curl https://ai-gateway.vercel.sh/typesafe/v1/systemone \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "typesafe-ai/jev",
    "state": "I was charged twice for my subscription.",
    "questions": {
      "refund": {
        "type": "noul",
        "instructions": "Is the customer asking for money back?"
      }
    }
  }'
systemone.ts
import { TypeSafeClient } from '@typesafe-ai/sdk';
 
const client = new TypeSafeClient({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh/typesafe',
});
 
const result = await client.systemOne({
  model: 'typesafe-ai/jev',
  state: 'I was charged twice for my subscription.',
  questions: {
    refund: {
      type: 'noul',
      instructions: 'Is the customer asking for money back?',
    },
  },
});
systemone.py
import os
import requests
 
response = requests.post(
    "https://ai-gateway.vercel.sh/typesafe/v1/systemone",
    headers={
        "Authorization": f"Bearer {os.environ['AI_GATEWAY_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "model": "typesafe-ai/jev",
        "state": "I was charged twice for my subscription.",
        "questions": {
            "refund": {
                "type": "noul",
                "instructions": "Is the customer asking for money back?",
            }
        },
    },
)
 
print(response.json()["answers"])

The response uses TypeSafe's field names:

{
  "model": "typesafe-ai/jev",
  "answers": {
    "refund": { "type": "noul", "noul": 0.98 }
  },
  "usage": { "input_tokens": 275, "output_tokens": 20 },
  "provider_metadata": {
    "gateway": {
      "routing": {
        "originalModelId": "typesafe-ai/jev",
        "resolvedProvider": "typesafe-ai",
        "canonicalSlug": "typesafe-ai/jev",
        "finalProvider": "typesafe-ai"
      },
      "cost": "0.00001155",
      "marketCost": "0.00001155",
      "surchargeCost": "0",
      "gatewayCost": "0.00001155",
      "generationId": "gen_..."
    }
  }
}

Decision fallbacks are an AI Gateway extension to the TypeSafe request. Add one conditional object to providerOptions.gateway.models to rerun a successful but uncertain decision with another model.

The official TypeSafe SDK forwards additional request properties at runtime, but its request type does not currently include providerOptions. Supply the extension through an intermediate object:

typesafe-decision-fallback.ts
import { TypeSafeClient } from '@typesafe-ai/sdk';
 
const client = new TypeSafeClient({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh/typesafe',
});
 
const request = {
  model: 'typesafe-ai/jev',
  state: 'I was charged twice and cannot sign in.',
  questions: {
    intent: {
      type: 'choice' as const,
      instructions: 'Which team should handle this?',
      criteria: {
        billing: 'Charges and refunds',
        account: 'Sign-in and account access',
      },
    },
  },
  providerOptions: {
    gateway: {
      models: [
        {
          model: 'openai/gpt-6-astra',
          when: { question: 'intent', confidenceBelow: 0.6 },
        },
      ],
    },
  },
};
 
const result = await client.systemOne(request);

If a language model returns the final Choice or Score answer, confidence: 0 and probabilities: {} mean those values are unavailable. They do not mean the model measured zero confidence. Native decision-model fallbacks preserve native confidence and probabilities.

Noul returns the fallback model's final P(true) normally. The response's top-level model echoes the model ID you requested when the primary answered, and names the fallback model whenever a fallback answered. AI Gateway routing metadata lists each model attempt and marks the one your condition triggered. Triggered requests bill both stages and report their combined usage.

When a condition matches, the response also carries these headers, listed in Access-Control-Expose-Headers so browser clients can read them:

HeaderValue
x-ai-gateway-decision-fallback-triggeredtrue
x-ai-gateway-decision-fallback-final-modelThe model that produced the returned answers
x-ai-gateway-decision-fallback-primary-modelThe primary model whose answers matched the condition
x-ai-gateway-decision-fallback-triggering-questionsA percent-encoded JSON array of the question IDs that matched. Read it with JSON.parse(decodeURIComponent(value))
x-ai-gateway-decision-fallback-triggering-questions-truncatedtrue when the question list was cut short. provider_metadata.gateway.routing has the full list

AI Gateway omits these headers when the condition doesn't match. Use them to detect a fallback when your client only reads TypeSafe's typed response fields.

AI Gateway also sends the deprecated x-ai-gateway-evaluation-fallback-* headers with identical values. Read the x-ai-gateway-decision-fallback-* headers in new code.

See Decision Fallbacks for Boolean probability conditions, compound policies, virtual models, the complete sentinel response, and two-stage cost and latency.

Errors use TypeSafe's shape, with a machine-readable code alongside the message:

{
  "message": "questions.refund.type: expected one of 'noul', 'choice', 'score'",
  "error_type": "invalid_request"
}

Errors returned by the model provider are passed through unchanged, so a client that already handles TypeSafe errors keeps working.

Last updated October 5, 2026

Was this helpful?

supported.