DeepSeek’s API is OpenAI-compatible, which means you can use the official openai npm package with zero code changes. This tutorial covers everything from your first API call to production-ready streaming with TypeScript — all through NovAI’s gateway for the lowest latency and pricing.
# Install the official OpenAI SDK
npm install openai
That’s it. No special DeepSeek SDK needed. The OpenAI package works perfectly because NovAI provides an OpenAI-compatible API endpoint.
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.NOVAI_API_KEY,
baseURL: 'https://aiapi-pro.com/v1',
});
const response = await client.chat.completions.create({
model: 'deepseek-v3.2',
messages: [
{ role: 'system', content: 'You are a helpful coding assistant.' },
{ role: 'user', content: 'Implement a debounce function in TypeScript' },
],
});
console.log(response.choices[0].message.content);
Set your API key as an environment variable:
# .env file
NOVAI_API_KEY=your-api-key-here
For real-time chat applications, streaming delivers tokens as they’re generated instead of waiting for the full response:
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.NOVAI_API_KEY,
baseURL: 'https://aiapi-pro.com/v1',
});
const stream = await client.chat.completions.create({
model: 'deepseek-v3.2',
messages: [{ role: 'user', content: 'Explain async/await in JavaScript' }],
stream: true,
});
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content || '';
process.stdout.write(text);
}
The OpenAI SDK ships with full TypeScript types. Here’s a production-ready typed wrapper:
import OpenAI from 'openai';
import type { ChatCompletionMessageParam } from 'openai/resources';
type Model = 'deepseek-v3.2' | 'deepseek-r1' | 'qwen-plus' | 'glm-4.6v';
const novai = new OpenAI({
apiKey: process.env.NOVAI_API_KEY!,
baseURL: 'https://aiapi-pro.com/v1',
});
async function chat(
messages: ChatCompletionMessageParam[],
model: Model = 'deepseek-v3.2'
): Promise<string> {
const response = await novai.chat.completions.create({
model,
messages,
temperature: 0.7,
max_tokens: 4096,
});
return response.choices[0].message.content ?? '';
}
// Usage
const answer = await chat([
{ role: 'user', content: 'What is the capital of France?' }
]);
Production applications need proper error handling. Here’s a robust pattern with exponential backoff:
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.NOVAI_API_KEY!,
baseURL: 'https://aiapi-pro.com/v1',
maxRetries: 3, // Built-in retry logic
timeout: 60 * 1000, // 60s timeout
});
async function safeChatCompletion(prompt: string) {
try {
const response = await client.chat.completions.create({
model: 'deepseek-v3.2',
messages: [{ role: 'user', content: prompt }],
});
return { success: true, data: response.choices[0].message.content };
} catch (error) {
if (error instanceof OpenAI.APIError) {
console.error(`API Error: ${error.status} ${error.message}`);
if (error.status === 429) {
// Rate limited — wait and retry
await new Promise(r => setTimeout(r, 5000));
return safeChatCompletion(prompt);
}
}
return { success: false, error: String(error) };
}
}
Building a chat API with streaming? Here’s how to pipe DeepSeek streaming directly to your frontend:
import express from 'express';
import OpenAI from 'openai';
const app = express();
const client = new OpenAI({
apiKey: process.env.NOVAI_API_KEY!,
baseURL: 'https://aiapi-pro.com/v1',
});
app.post('/api/chat', async (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const stream = await client.chat.completions.create({
model: 'deepseek-v3.2',
messages: req.body.messages,
stream: true,
});
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content;
if (text) res.write(`data: ${JSON.stringify({ text })}\n\n`);
}
res.write('data: [DONE]\n\n');
res.end();
});
app.listen(3000);
One of NovAI’s biggest advantages is access to multiple models through a single API key. Route different tasks to the optimal model:
const ROUTING = {
coding: 'deepseek-v3.2', // Best for code generation
reasoning: 'deepseek-r1', // Complex math/logic
vision: 'glm-4.6v', // Image understanding
longDoc: 'minimax-text-01', // 1M token context
free: 'glm-4.6v-flash', // Free tier, no cost
multilingual: 'qwen-plus', // Chinese ↔ English
} as const;
type TaskType = keyof typeof ROUTING;
async function smartChat(task: TaskType, prompt: string) {
return client.chat.completions.create({
model: ROUTING[task],
messages: [{ role: 'user', content: prompt }],
});
}
// Examples
await smartChat('coding', 'Write a Redis cache wrapper');
await smartChat('reasoning', 'Prove that sqrt(2) is irrational');
await smartChat('free', 'Classify this text: ...');
| Model | Input $/1M | Output $/1M | Best For |
|---|---|---|---|
| DeepSeek-v3.2 | $0.20 | $0.80 | Code gen, reasoning, chat |
| DeepSeek-R1 | $1.40 | $5.60 | Math, logic, complex reasoning |
| Qwen-Plus | $0.80 | $0.80 | Multilingual, instruction following |
| GLM-4.6V | $0.40 | $1.20 | Vision, image understanding |
| GLM-4.6V-Flash | FREE | FREE | Testing, prototyping |
| MiniMax-Text-01 | $0.20 | $1.60 | Long documents (1M context) |
If you’re building a browser-based chat, here’s how to consume the SSE stream from the Express endpoint above:
async function chatStream(messages) {
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages }),
});
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.startsWith('data: ') && line !== 'data: [DONE]') {
const { text } = JSON.parse(line.slice(6));
document.getElementById('output').textContent += text;
}
}
}
}
Free API key, free GLM-4.6V-Flash model, and DeepSeek from $0.20/1M tokens. Pay with PayPal or USDT.
Get Started Free →