Use Obscurify.ai with the Vercel AI SDK

Obscurify.ai’s API is OpenAI-compatible, so the Vercel AI SDK talks to it through the @ai-sdk/openai-compatible package. No Obscurify-specific package is needed.

You need an Obscurify.ai account (a random account number, no email) and its API key: create an account, then click Show API Key on the account page. The API works on every plan with a positive balance. New accounts may get $1 of starter credit while this month’s promo budget lasts.

Install

npm install ai @ai-sdk/openai-compatible zod

Create the provider

import { createOpenAICompatible } from '@ai-sdk/openai-compatible';

export const obscurify = createOpenAICompatible({
  name: 'obscurify',
  baseURL: 'https://obscurify.ai/v1',
  apiKey: process.env.OBSCURIFY_API_KEY,
  includeUsage: true,
});

Set OBSCURIFY_API_KEY to your key (sk-obs1_...).

Generate text

import { generateText } from 'ai';

const { text } = await generateText({
  model: obscurify('meta-llama/llama-3.3-70b-instruct'),
  prompt: 'Say hello in one short sentence.',
});

Stream, with reasoning

import { streamText } from 'ai';

const result = streamText({
  model: obscurify('deepseek/deepseek-v4-flash'),
  prompt: 'Count from 1 to 5, comma separated.',
  providerOptions: { obscurify: { reasoningEffort: 'high' } },
});

for await (const part of result.fullStream) {
  if (part.type === 'reasoning-delta') process.stdout.write(`[thinking] ${part.text}`);
  if (part.type === 'text-delta') process.stdout.write(part.text);
}

The accepted reasoningEffort levels depend on the model; see each model’s page in the model list.

Tools

import { generateText, tool, stepCountIs } from 'ai';
import { z } from 'zod';

const { text } = await generateText({
  model: obscurify('z-ai/glm-5.3'),
  tools: {
    weather: tool({
      description: 'Get the weather in a city',
      inputSchema: z.object({ city: z.string() }),
      execute: async ({ city }) => ({ city, tempC: 18 }),
    }),
  },
  stopWhen: stepCountIs(3),
  prompt: 'What is the weather in Paris? Use the tool, then answer in one sentence.',
});

Structured output

Turn on supportsStructuredOutputs so the SDK sends a JSON schema:

import { generateText, Output } from 'ai';
import { z } from 'zod';

const obscurifyJson = createOpenAICompatible({
  name: 'obscurify',
  baseURL: 'https://obscurify.ai/v1',
  apiKey: process.env.OBSCURIFY_API_KEY,
  includeUsage: true,
  supportsStructuredOutputs: true,
});

const { output } = await generateText({
  model: obscurifyJson('z-ai/glm-5.3'),
  output: Output.object({ schema: z.object({ city: z.string(), country: z.string() }) }),
  prompt: 'Name the capital of France as city and country.',
});

Models

Model IDs use the <lab>/<model> form, for example deepseek/deepseek-v4-flash, z-ai/glm-5.3, moonshotai/kimi-k2-0905, qwen/qwen3-coder or meta-llama/llama-3.3-70b-instruct. GET https://obscurify.ai/v1/models lists every current ID with its context length and price; the model list shows the plan each model needs. Frontier models (GPT, Claude, Gemini) need the Casual or Pro plan; uncensored models need Pro. See pricing.

What works

  • generateText and streamText: yes.
  • Tool calling and multi-step tools (stopWhen): yes, on models that support tools.
  • Reasoning: yes; reasoning text arrives as reasoning-delta parts.
  • Structured output (Output.object with supportsStructuredOutputs: true): yes, checked on z-ai/glm-5.3.
  • Usage: reported on streamed and non-streamed calls (with includeUsage: true), including what the call cost (usage.raw.cost, in USD).

Questions or problems: contact us (email optional).

Last checked with ai 7.0.155 and @ai-sdk/openai-compatible 3.0.80 on 2026-10-28.