Skip to content

About

Official Node.js SDK for DEVUP AI — Algeria's AI inference gateway. OpenAI-compatible, 170+ models, DZD billing.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

DEVUP AI

DEVUP AI — Official Node.js SDK

Build with leading AI models. Pay in Algerian Dinar.

A TypeScript-first SDK for chat, images, embeddings, audio, video, and specialized inference through one OpenAI-compatible API.

npm version MIT License Node.js version TypeScript Ready OpenAI Compatible DEVUP AI Status

Documentation · Dashboard · API Keys · Models · Status · npm


Overview

devupai is the official Node.js and TypeScript SDK for DEVUP AI, an AI inference gateway built for developers and businesses in Algeria.

It gives you one consistent interface for:

  • Chat and reasoning
  • Image generation and editing
  • Text embeddings
  • Text-to-speech and transcription
  • Video generation and editing
  • Specialized native inference
  • Model discovery, account balance, and health operations
  • Vercel AI SDK integrations

Core client: zero runtime dependencies.
Vercel AI SDK provider: available through the optional devupai/ai export.

Contents


Why DEVUP AI

Capability What it gives you
Billing in DZD Track AI usage and costs directly in Algerian Dinar.
Local payment access Top up with supported local payment methods such as Edahabia and CIB.
OpenAI-compatible API Use familiar request shapes and migration patterns.
Multimodal inference Access text, images, embeddings, audio, video, and specialized models from one SDK.
TypeScript-first contracts Typed public requests and responses derived from the DEVUP AI OpenAPI specification.
Modern runtime support Designed for Node.js 18+, browsers, and Edge-compatible environments.
Vercel AI SDK provider Use generateText, streamText, route handlers, and UI streaming through devupai/ai.
Operational visibility Query models, account balance, service health, and billing metadata.

Installation

Core SDK

npm install devupai

Core SDK + Vercel AI SDK

npm install devupai ai @ai-sdk/openai-compatible @ai-sdk/provider

Quick Start

import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function main() {
  const response = await client.chat.completions.create({
    model: "deepseek-ai/DeepSeek-V4-Pro",
    messages: [
      {
        role: "system",
        content: "You are a concise technical assistant.",
      },
      {
        role: "user",
        content: "Explain artificial intelligence in one paragraph.",
      },
    ],
  });

  console.log(response.choices[0]?.message?.content);
  console.log("Cost:", response._devup?.cost_dzd, "DZD");
}

main().catch(console.error);

Capability Matrix

Capability SDK method Authentication
Chat completions client.chat.completions.create() Required
Image generation client.images.generate() Required
Image editing client.images.edit() Required
Image proxy client.images.proxy() Public
Embeddings client.embeddings.create() Required
Text-to-speech client.audio.speech.create() Required
Transcription client.audio.transcriptions.create() Required
Video generation client.video.generations.create() Required
Video editing client.video.edits.create() Required
Native inference client.inference.run() Required
Model discovery client.models.list() Public
Account balance client.balance.retrieve() Required
Service health client.health.check() Public
Webhook verification client.webhooks.verifySignature() None (local computation)
Webhook construction client.webhooks.constructEvent() None (local computation)

Public operations omit the Authorization header.


Core SDK

Chat Completions

import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function generateResponse() {
  const response = await client.chat.completions.create({
    model: "deepseek-ai/DeepSeek-V4-Pro",
    messages: [
      {
        role: "user",
        content: "What is retrieval-augmented generation?",
      },
    ],
    temperature: 0.4,
    max_tokens: 800,
  });

  console.log(response.choices[0]?.message?.content);
  console.log("Cost:", response._devup?.cost_dzd, "DZD");
  console.log("Balance:", response._devup?.balance_dzd, "DZD");
}

generateResponse().catch(console.error);

Streaming

Streaming responses can contain:

  1. Standard OpenAI-compatible delta chunks.
  2. A final DEVUP billing chunk containing _devup.
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function streamResponse() {
  const stream = await client.chat.completions.create({
    model: "deepseek-ai/DeepSeek-V4-Pro",
    messages: [
      {
        role: "user",
        content: "Write a short poem about Algeria.",
      },
    ],
    stream: true,
  });

  for await (const chunk of stream) {
    if ("_devup" in chunk) {
      console.log("\n");
      console.log("Cost:", chunk._devup.cost_dzd, "DZD");
      console.log("Remaining balance:", chunk._devup.balance_dzd, "DZD");
      continue;
    }

    process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
  }
}

streamResponse().catch(console.error);

Reasoning and Thinking Output

Reasoning models may return internal thinking traces via reasoning_content on the message object, along with optional reasoning_tokens in usage.

import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function runReasoning() {
  // WARNING: Set max_tokens high enough to accommodate BOTH reasoning trace and final answer.
  // In testing, Qwen/Qwen3-14B with max_tokens: 600 exhausted its token budget during generation,
  // returning finish_reason: "length" with reasoning_content: null and a truncated answer,
  // while the request was fully billed. Always check finish_reason.
  const response = await client.chat.completions.create({
    model: "inclusionAI/Ling-3.0-flash",
    messages: [
      {
        role: "user",
        content: "Prove whether 3571 is a prime number.",
      },
    ],
    max_tokens: 2048,
  });

  const choice = response.choices[0];
  if (!choice) return;

  // Guard against truncated generation when token budget is exhausted
  if (choice.finish_reason === "length") {
    console.warn("Generation truncated: token limit reached before completion.");
  }

  // reasoning_content is populated by some providers and null for others
  if (choice.message?.reasoning_content) {
    console.log("Reasoning trace:\n", choice.message.reasoning_content);
  }

  console.log("Answer:\n", choice.message?.content);

  // reasoning_tokens is optional (returned by 1 of 5 tested providers)
  if (response.usage?.reasoning_tokens !== undefined) {
    console.log("Reasoning tokens:", response.usage.reasoning_tokens);
  }

  // prompt_tokens_details can be null or omitted depending on provider
  if (response.usage?.prompt_tokens_details?.cached_tokens) {
    console.log("Cached prompt tokens:", response.usage.prompt_tokens_details.cached_tokens);
  }

  console.log("Cost:", response._devup?.cost_dzd, "DZD");
}

runReasoning().catch(console.error);

Images

Generate an image
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function generateImage() {
  const response = await client.images.generate({
    model: "black-forest-labs/FLUX.1-schnell",
    prompt: "A cinematic view of Algiers at sunset",
    size: "1024x1024",
  });

  console.log(response.data[0]?.url);
  console.log("Cost:", response._devup?.cost_dzd, "DZD");
}

generateImage().catch(console.error);
Edit an image
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function editImage() {
  const image = new Blob(["image-data"], {
    type: "image/png",
  });

  const response = await client.images.edit({
    model: "black-forest-labs/FLUX.1-schnell",
    image,
    prompt: "Add a red sports car in the foreground",
  });

  console.log(response.data[0]?.url);
}

editImage().catch(console.error);

Embeddings

import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function createEmbeddings() {
  const response = await client.embeddings.create({
    model: "BAAI/bge-m3",
    input: ["Hello world", "مرحبا بالعالم", "Bonjour le monde"],
  });

  console.log(response.data[0]?.embedding);
  console.log("Dimensions:", response.data[0]?.embedding?.length);
}

createEmbeddings().catch(console.error);

Audio

Text-to-speech
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function createSpeech() {
  const response = await client.audio.speech.create({
    model: "kokoro",
    input: "Welcome to DEVUP AI.",
    voice: "af_sky",
  });

  console.log("Audio URL:", response.url);
  console.log("Cost:", response._devup.cost_dzd, "DZD");
  console.log("Balance:", response._devup.balance_dzd, "DZD");
}

createSpeech().catch(console.error);
Speech-to-text
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function transcribeAudio() {
  const audio = new Blob(["audio-data"], {
    type: "audio/wav",
  });

  const transcript = await client.audio.transcriptions.create({
    file: audio,
    model: "openai/whisper-large-v3-turbo",
    language: "ar",
    response_format: "json",
  });

  console.log(transcript.text);
}

transcribeAudio().catch(console.error);

Video

Generate a video
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function generateVideo() {
  const response = await client.video.generations.create({
    model: "Wan-AI/Wan2.1-T2V-14B",
    prompt: "A camel walking through the Sahara at golden hour",
    width: 1280,
    height: 720,
  });

  console.log(response.data[0]?.url);
  console.log("Cost:", response._devup?.cost_dzd, "DZD");
}

generateVideo().catch(console.error);
Edit a video
import DevupAI, { type VideoKeyPoint } from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function editVideo() {
  const video = new Blob(["video-data"], {
    type: "video/mp4",
  });

  const keyPoints: VideoKeyPoint[] = [
    {
      x: 320,
      y: 240,
      type: "positive",
    },
  ];

  const response = await client.video.edits.create({
    model: "video-edit-model",
    video,
    prompt: "Enhance the subject while preserving the background",
    key_points: keyPoints,
    preserve_audio: true,
  });

  console.log(response.data[0]?.url);
}

editVideo().catch(console.error);

Native Inference

Native inference supports specialized models whose inputs and outputs do not follow a standard OpenAI schema.

The response type defaults to unknown. Provide a generic type when your application knows the expected result shape.

import DevupAI from "devupai";

interface RerankResponse {
  results: Array<{
    index: number;
    score: number;
  }>;
}

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

```typescript
async function rerankDocuments() {
  const response = await client.rerank.create({
    model: "Qwen/Qwen3-Reranker-8B",
    query: "What is DEVUP AI?",
    documents: [
      "DEVUP AI is an AI inference gateway.",
      "Algiers is the capital of Algeria.",
    ],
    top_n: 1,
  });

  console.log(response.results);
}

rerankDocuments().catch(console.error);

Models, Balance, and Health

import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function inspectAccount() {
  const health = await client.health.check();
  console.log("API status:", health.status);

  const models = await client.models.list();
  console.log("Available models:", models.data.length);

  const balance = await client.balance.retrieve();
  console.log("Balance:", balance.balance_dzd, "DZD");
}

inspectAccount().catch(console.error);

Image Proxy

The image proxy returns a native Response, giving you direct access to its headers and binary body.

import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function proxyImage() {
  const response = await client.images.proxy({
    url: "https://example.com/image.jpg",
  });

  console.log("Content-Type:", response.headers.get("content-type"));

  const image = await response.arrayBuffer();
  console.log("Image bytes:", image.byteLength);
}

proxyImage().catch(console.error);

Webhooks

Verify incoming webhook deliveries and construct typed event payloads.

You can import standalone helper functions directly or access them via client.webhooks.

Verifying and Parsing Events (Express)

import express from "express";
import {
  constructWebhookEvent,
  DevupWebhookVerificationError,
  type WebhookEvent,
} from "devupai";

const app = express();
const endpointSecret = process.env.DEVUP_WEBHOOK_SECRET!;

// express.raw() is required: express.json() parses and alters the body bytes, causing verification to always fail
app.post(
  "/webhook",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    const signature = req.headers["x-devup-signature"];
    if (typeof signature !== "string") {
      return res.status(400).send("Missing signature header");
    }

    try {
      const event: WebhookEvent = await constructWebhookEvent({
        rawBody: req.body,
        signatureHeader: signature,
        secret: endpointSecret,
      });

      if (event.status === "succeeded") {
        console.log("Inference succeeded:", event.id);
        console.log("Results:", event.results);
        console.log("Cost:", event.cost_dzd, "DZD");
      } else {
        console.error("Inference failed:", event.id);
        console.error("Error:", event.error.type, event.error.message);
      }

      res.status(200).json({ received: true });
    } catch (err) {
      if (err instanceof DevupWebhookVerificationError) {
        console.error(`Webhook verification failed (${err.reason}):`, err.message);
        return res.status(400).send(`Webhook Error: ${err.message}`);
      }
      res.status(500).send("Server Error");
    }
  }
);

app.listen(3000, () => console.log("Webhook receiver listening on port 3000"));

Boolean Signature Verification

For workflows that prefer conditional branching over exception handling, use verifyWebhookSignature:

import { verifyWebhookSignature } from "devupai";

async function handleWebhook(rawBody: string | Uint8Array, signatureHeader: string) {
  const isValid = await verifyWebhookSignature({
    rawBody,
    signatureHeader,
    secret: process.env.DEVUP_WEBHOOK_SECRET!,
    toleranceSeconds: 300,
  });

  if (!isValid) {
    console.warn("Rejected unauthorized or expired webhook delivery");
    return false;
  }

  const payload = JSON.parse(
    typeof rawBody === "string" ? rawBody : new TextDecoder().decode(rawBody)
  );
  return payload;
}

Verification Failure Reasons

When constructWebhookEvent fails, it throws a DevupWebhookVerificationError with a specific reason field:

Reason When it fires What to do
malformed_header The X-DevUp-Signature header is missing, empty, lacks a valid t= timestamp, or contains no v1= signatures. Verify your web server forwards the X-DevUp-Signature header unmodified.
timestamp_outside_tolerance The difference between the request timestamp t and local system time exceeds toleranceSeconds (default 300s). This usually indicates server clock skew rather than a forged request. Synchronize your server clock with NTP or increase toleranceSeconds.
no_matching_signature None of the v1 signatures in the header match the computed HMAC over the raw body and timestamp. Confirm that secret matches your dashboard webhook secret, and ensure rawBody is the untouched raw byte stream (not re-serialized JSON).
invalid_json The signature was successfully verified, but the payload body is not valid JSON. Check upstream payload integrity and ensure no middle-tier proxy truncated the body.

Deduplication

Always key idempotency checks on the X-DevUp-Delivery-Id header. The delivery ID is generated once and remains identical across all retry attempts. Because the t= timestamp and signature are recomputed on every attempt, a consumer keying idempotency on the signature will treat legitimate retries as new events and process duplicate results.

During a 24h secret rotation window, DEVUP AI attaches multiple v1 signatures (computed with both the previous and new secret); accepting any matching signature allows zero-downtime secret rotations without coordinated cutovers.


Vercel AI SDK

Use the optional devupai/ai export with the Vercel AI SDK.

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

Generate text

import { generateText } from "ai";
import { createDevupAI } from "devupai/ai";

const devupai = createDevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function main() {
  const { text } = await generateText({
    model: devupai("deepseek-ai/DeepSeek-V4-Pro"),
    prompt: "Explain neural networks in simple terms.",
  });

  console.log(text);
}

main().catch(console.error);

Stream text

import { streamText } from "ai";
import { createDevupAI } from "devupai/ai";

const devupai = createDevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function main() {
  const result = streamText({
    model: devupai("deepseek-ai/DeepSeek-V4-Pro"),
    prompt: "Write a short story set in Algiers.",
  });

  for await (const text of result.textStream) {
    process.stdout.write(text);
  }
}

main().catch(console.error);

Next.js plain-text streaming

import { streamText } from "ai";
import { createDevupAI } from "devupai/ai";

const devupai = createDevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

export async function POST(request: Request) {
  const body = await request.json();

  const result = streamText({
    model: devupai("deepseek-ai/DeepSeek-V4-Pro"),
    messages: body.messages,
  });

  return result.toTextStreamResponse();
}

Next.js UI streaming

import { streamText } from "ai";
import { createDevupAI } from "devupai/ai";

const devupai = createDevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

export async function POST(request: Request) {
  const body = await request.json();

  const result = streamText({
    model: devupai("deepseek-ai/DeepSeek-V4-Pro"),
    messages: body.messages,
  });

  return result.toUIMessageStreamResponse();
}

Configuration

import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
  baseURL: "https://api.devupai.com/v1",
  headers: {
    "X-Application-Name": "my-application",
  },
});
Option Type Required Default Description
apiKey string Yes — Your DEVUP AI API key.
baseURL string No https://api.devupai.com/v1 DEVUP AI API base URL.
headers Record<string, string> No — Custom headers included in client requests.

Protected authentication and content-type headers are managed by the SDK.


Request Options

Resource methods accept common request options alongside their request parameters.

Option Type Description
signal AbortSignal | null Cancel a request with an external abort signal.
timeout number Abort the request after the specified number of milliseconds.
headers Record<string, string> Add request-specific custom headers.
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function requestWithTimeout() {
  const response = await client.chat.completions.create({
    model: "deepseek-ai/DeepSeek-V4-Pro",
    messages: [
      {
        role: "user",
        content: "Summarize Algeria in three sentences.",
      },
    ],
    timeout: 30_000,
    headers: {
      "X-Request-Source": "documentation-example",
    },
  });

  console.log(response.choices[0]?.message?.content);
}

requestWithTimeout().catch(console.error);

TypeScript

The SDK exposes typed public request and response contracts derived from the DEVUP AI OpenAPI specification, curated ergonomic request types, typed streaming chunks, and safe generics for model-dependent native inference.

import DevupAI, {
  type ChatCompletion,
  type ChatCompletionCreateParams,
} from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

const request: Omit<ChatCompletionCreateParams, "stream"> = {
  model: "deepseek-ai/DeepSeek-V4-Pro",
  messages: [
    {
      role: "user",
      content: "Hello from TypeScript.",
    },
  ],
};

async function typedCompletion(): Promise<ChatCompletion> {
  return client.chat.completions.create(request);
}

typedCompletion()
  .then((response) => {
    console.log(response.choices[0]?.message?.content);
  })
  .catch(console.error);

Error Handling

API and transport failures are represented by DevupAPIError.

Property Type Description
status number HTTP status code, or 0 for a network failure.
message string Human-readable error message.
type string | undefined API error category when available.
code string | undefined Machine-readable API error code when available.
requestId string | null DEVUP request identifier when returned.
retryAfter string | null Raw Retry-After response header value.
headers Record<string, string> Normalized response headers.
cause unknown Original underlying error when available.
import DevupAI, { DevupAPIError } from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY!,
});

async function main() {
  try {
    await client.chat.completions.create({
      model: "deepseek-ai/DeepSeek-V4-Pro",
      messages: [
        {
          role: "user",
          content: "Hello.",
        },
      ],
    });
  } catch (error) {
    if (error instanceof DevupAPIError) {
      console.error("DEVUP API request failed");
      console.error("Status:", error.status);
      console.error("Message:", error.message);
      console.error("Type:", error.type);
      console.error("Code:", error.code);
      console.error("Request ID:", error.requestId);
      console.error("Retry-After:", error.retryAfter);
      return;
    }

    throw error;
  }
}

main().catch(console.error);

Webhook signature and payload verification failures throw DevupWebhookVerificationError. This is not an API error, carries no HTTP status code, and represents local validation failures.

Property Type Description
name "DevupWebhookVerificationError" Error class identifier.
message string Human-readable description of the verification failure.
reason DevupWebhookVerificationErrorReason Machine-readable failure reason code.
cause unknown Underlying error when available (e.g. SyntaxError on invalid JSON).

Runtime and Security

  • Node.js 18+ support
  • Browser and Edge-compatible request primitives
  • Webhook signature verification uses Web Crypto (globalThis.crypto.subtle) and runs asynchronously across Node.js 18+, Edge runtimes, Cloudflare Workers, Deno, Bun, and browsers with zero dependencies
  • Protected authentication and content-type headers
  • Public methods that omit authorization
  • Timeout and external abort-signal support
  • Native Response support for image proxy operations
  • No API key persistence performed by the SDK

Store API keys in environment variables or a server-side secret manager.

Never expose API keys in browser bundles, public repositories, or client-side environment variables.


Models

DEVUP AI supports models across multiple modalities:

  • Chat and reasoning
  • Image generation and editing
  • Embeddings
  • Speech recognition
  • Text-to-speech
  • Video generation and editing
  • Reranking and specialized inference

Model availability may evolve over time. The live catalog is the source of truth:

Browse available models →


Get an API Key

  1. Create an account at devupai.com.
  2. Open the DEVUP AI Dashboard.
  3. Top up your balance using a supported payment method.
  4. Generate an API key from the API Keys page.
  5. Store it securely as DEVUP_API_KEY.
DEVUP_API_KEY=sk-devup-your-api-key

Resources

Resource Link
Website devupai.com
Documentation docs.devupai.com
Dashboard devupai.com/dashboard
API Keys devupai.com/dashboard/api-keys
Models devupai.com/models
Status status.devupai.com
npm npmjs.com/package/devupai

License

The DEVUP AI Node.js SDK is released under the MIT License.

Built for Algeria. Compatible with the global AI ecosystem.

Website · Documentation · npm

About

Official Node.js SDK for DEVUP AI — Algeria's AI inference gateway. OpenAI-compatible, 170+ models, DZD billing.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages