Volver al blog

API y SDKGuía

Primera solicitud en C# con openai-dotnet: endpoint, clave, respuesta

Envía tu primera finalización de chat desde una app de consola en C#: establece el Endpoint en la librería oficial de OpenAI para .NET, lee la clave desde env, imprime la respuesta y el motivo de finalización.

Por CheapTokens TeamPublicado el 5 min de lectura

Portada: C# y la librería OpenAI para .NET conectadas al endpoint de CheapTokens
En esta página
  1. Qué necesitas
  2. Crea la app de consola
  3. El código, línea por línea
  4. Qué deberías ver
  5. Cambiar un servicio existente
  6. Cuánto cuesta una solicitud
  7. Si no funciona

Para enviar una solicitud desde C# a CheapTokens, conserva la librería oficial de OpenAI para .NET y establece OpenAIClientOptions.Endpoint en https://api.cheaptokens.dev/v1. Pasa el id completo del modelo, por ejemplo deepseek-ai/DeepSeek-V4-Flash-0731, y lee la clave desde una variable de entorno. Las llamadas ChatClient y CompleteChat se mantienen exactamente como están en los ejemplos de OpenAI.

Supón que ya tienes un servicio ASP.NET que habla con OpenAI y quieres probar otro endpoint y otro modelo sin tocar el resto del código. Antes de conectar nada, comprueba en una pequeña app de consola las tres cosas que suelen fallar (clave, endpoint, id del modelo). Eso es lo que construimos aquí. Los detalles siguientes provienen del README de la librería en GitHub (openai/openai-dotnet, consultado el 5 de noviembre de 2026) y de la documentación de CheapTokens: la página de docs tiene la misma URL base.

Qué necesitas#

El paquete se llama OpenAI en NuGet. La última versión estable a 5 de noviembre de 2026 es la 2.15.0 (su entrada de changelog está fechada el 4 de noviembre). Tiene como destino .NET 8 y .NET Standard 2.0, y el README dice que funciona con todas las aplicaciones .NET Standard 2.0, así que un proyecto más antiguo también sirve.

Tres valores van en la app:

  • URL base: https://api.cheaptokens.dev/v1 (compatible con OpenAI Chat Completions);
  • id del modelo: deepseek-ai/DeepSeek-V4-Flash-0731. Usa el id completo, el nombre corto de una tabla de precios no se acepta. DeepSeek-V4-Flash tiene una ventana de contexto de 380K y hasta 32.768 tokens de salida por respuesta, un solo precio a cualquier hora del día;
  • una clave de API de tu cuenta de CheapTokens, guardada en una variable de entorno. Si no sabes cómo guardarla, lee cómo guardar una clave de API de forma segura.

Crea la app de consola#

Paso a paso

Crea el proyecto y ejecútalo

Crea un proyecto de consola

bash
dotnet new console -o FirstRequest
cd FirstRequest

Añade el paquete

bash
dotnet add package OpenAI

Pon la clave en una variable de entorno

En bash o zsh:

bash
export CHEAPTOKENS_API_KEY=your-key

En Windows PowerShell:

powershell
$env:CHEAPTOKENS_API_KEY = "your-key"

Pega el código y ejecuta

Sustituye el contenido de Program.cs por el código de la siguiente sección y luego ejecuta dotnet run.

Terminal con los cinco comandos que crean y ejecutan la app de consola
Los cinco comandos: crear el proyecto, entrar en la carpeta, añadir el paquete, establecer la clave, ejecutar.

El código, línea por línea#

csharp
using System.ClientModel;
using OpenAI;
using OpenAI.Chat;

string? apiKey = Environment.GetEnvironmentVariable("CHEAPTOKENS_API_KEY");
if (string.IsNullOrEmpty(apiKey))
{
    Console.WriteLine("Set CHEAPTOKENS_API_KEY first.");
    return;
}

ChatClient client = new(
    model: "deepseek-ai/DeepSeek-V4-Flash-0731",
    credential: new ApiKeyCredential(apiKey),
    options: new OpenAIClientOptions
    {
        Endpoint = new Uri("https://api.cheaptokens.dev/v1")
    });

ChatCompletion completion = client.CompleteChat("Explain in two sentences what a token is.");

Console.WriteLine(completion.Content[0].Text);
Console.WriteLine($"finish_reason: {completion.FinishReason}");

El README muestra este patrón para "un proxy o un LLM autoalojado compatible con OpenAI": el endpoint va en OpenAIClientOptions, la clave en un ApiKeyCredential (vive en System.ClientModel, de ahí el primer using). La comprobación del principio es nuestra: da un mensaje claro si la variable no está definida.

CompleteChat con una cadena simple envía un mensaje de usuario y espera la respuesta completa. El texto de la respuesta está en completion.Content[0].Text. El motivo de finalización está en completion.FinishReason.

Flujo: clave desde env, ChatClient con Endpoint, CompleteChat, texto y FinishReason
Qué ocurre en el programa desde la clave hasta la respuesta impresa.

Qué deberías ver#

Deberías obtener una breve explicación sobre tokens y una línea con el motivo de finalización; tras un final normal es Stop (el README compara FinishReason con ChatFinishReason.Stop). El texto de la respuesta cambia de una ejecución a otra.

La segunda línea es la que merece la pena leer. El README compara FinishReason con ChatFinishReason.Stop (el modelo terminó por sí solo) y ChatFinishReason.ToolCalls (el modelo quiere llamar a una herramienta). Cualquier cosa distinta de Stop en un chat simple significa que la respuesta terminó por otro motivo, y el sospechoso habitual es un límite de longitud. Si ves una respuesta que se corta a mitad de frase, este artículo explica finish_reason y max_tokens.

Cambiar un servicio existente#

Si tu servicio ya crea un ChatClient para OpenAI, cambias dos cosas: la cadena del modelo y las opciones. El resto de las llamadas siguen funcionando.

Comparar

El mismo cliente, dos líneas cambiadas

Antes

csharp
ChatClient client = new(
    model: "your-current-model",
    credential: new ApiKeyCredential(apiKey));

Después

csharp
ChatClient client = new(
    model: "deepseek-ai/DeepSeek-V4-Flash-0731",
    credential: new ApiKeyCredential(apiKey),
    options: new OpenAIClientOptions
    {
        Endpoint = new Uri("https://api.cheaptokens.dev/v1")
    });

Para solicitudes cortas hay una segunda opción: zai-org/GLM-5.3-Flash (390K de contexto, hasta 8.192 tokens de salida). Solo cambias la cadena model. Una lista de ids que tu clave puede usar está a una solicitud de distancia, consulta Listar modelos con GET /v1/models.

Cuánto cuesta una solicitud#

Supón que un servicio gestiona 1.000 solicitudes al día, cada una de unas 300 tokens de entrada y 400 tokens de salida. Una solicitud así cuesta $0.000045 en DeepSeek-V4-Flash. La tabla siguiente muestra las mismas 1.000 solicitudes en los tres modelos junto a OpenRouter. En total, contando entrada y salida juntas, DeepSeek-V4-Flash es más barato que OpenRouter. Los precios actuales están en la página de precios, y la página de DeepSeek enumera lo que ofrece el modelo.

Modelo Por solicitud 1000 solicitudes OpenRouter, 1000 solicitudes
GLM-5.3-Flash $0.000022 $0.022 $0.0433
DeepSeek-V4-Flash $0.000045 $0.0445 $0.077
MiniMax-M2.7 $0.000075 $0.075 $0.90

300 tokens de entrada y 400 tokens de salida por solicitud. Los precios por 1M de tokens son actuales y cambian junto con nuestras tarifas; la columna de OpenRouter muestra precios de referencia para la misma carga de trabajo.

Si no funciona#

  • 401. Falta la clave o es incorrecta. Imprime si la variable está definida (la comprobación del código lo hace) y asegúrate de que dotnet run se inicia en la misma terminal donde ejecutaste export (o $env:): la variable solo vive en esa sesión.
  • 404. Lo más habitual es el id del modelo: un nombre corto en lugar del deepseek-ai/DeepSeek-V4-Flash-0731 completo, o un endpoint sin /v1 (comprueba también que OpenAIClientOptions se pasa realmente a ChatClient). Los detalles están en API 401 o 404: clave, URL base o id de modelo incorrectos.
  • error CS0246: The type or namespace name 'ApiKeyCredential' could not be found. Falta la línea using System.ClientModel; al principio de Program.cs.

La misma idea en otro lenguaje: la versión en Go con openai-go.