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
generateTextandstreamText: yes.- Tool calling and multi-step tools (
stopWhen): yes, on models that support tools. - Reasoning: yes; reasoning text arrives as
reasoning-deltaparts. - Structured output (
Output.objectwithsupportsStructuredOutputs: true): yes, checked onz-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.