SDK OpenAI Python: base_url de Carpe Diem, clave cdm_, coste real

Este tutorial sirve para llamar a Carpe Diem desde un script Python, con el SDK OpenAI que ya usa: chat, lista de modelos, cambio de modelo, streaming, lectura del coste. Solo se instala un paquete, openai==3.36.0, en un venv. Luego bastan dos campos: base_url hacia https://carpe-diem.xyz/api/operator/v1 y una clave cdm_. Nuestra prueba del 22 de octubre de 2026 obtuvo pong de llama-3.3-70b por 524 micro-USDC; el mismo cliente listó 392 modelos.

Ilustración generada con seedream-v5-lite en Carpe Diem.
Qué necesita
Nada más que Python, un venv, el SDK OpenAI fijado y una clave Carpe Diem. Sin CLI de Carpe Diem, sin SDK propio.
- Una cuenta Carpe Diem con créditos o una cuenta prepaid, y una clave
cdm_(pestaña API Keys del panel del comprador). - Python 3.10 o superior (el paquete
openai==3.36.0lo exige). pipen un venv, para fijaropenai==3.36.0.
Al terminar podrá: enviar un chat.completions.create (paso 3), listar identificadores con models.list() (paso 3), leer x-carpe-cost-usdc-micro (paso 4), pasar de llama-3.3-70b a claude-haiku-5-5 cambiando una cadena (paso 5) y hacer streaming de un haiku (paso 6).
Paso 1: crear una clave cdm_
Abra Credits & keys, pestaña API Keys. Las claves empiezan por cdm_ y se muestran una sola vez. Elija cómo paga la clave (Credits o Prepaid), un nombre si quiere, luego Create a key.
Credits: saldo de uso, 1 crédito = 0,01 $, sin retirada. Prepaid: una cuenta que usted posee; el protocolo solo cobra el coste de cada llamada, retirada posible. Ambos se liquidan en USDC en Base (guía, §4.1). Una tercera vía, x402, paga desde una wallet sin clave cdm_; este tutorial no la trata.

Cópiela de inmediato en un gestor de secretos: no se volverá a mostrar. En la terminal del tutorial:
export OPENAI_API_KEY=cdm_your_key_here
Para probar un modelo sin código, queda Create Hub.
Paso 2: instalar openai 3.36.0
python3 -m venv .venv
.venv/bin/pip install openai==3.36.0
No hemos probado otra versión del paquete. El cliente OpenAI envía POST /chat/completions bajo base_url. En Carpe Diem, base_url debe incluir ya /v1:
https://carpe-diem.xyz/api/operator/v1
No https://carpe-diem.xyz/api/operator: es la URL del adaptador Anthropic, otro protocolo. La guía SDK lo dice al inicio de la página, justo encima del ejemplo Python OpenAI.

Paso 3: enviar el primer mensaje
Fichero hello.py (el cliente se recrea ahí, como en cada extracto):
import os
from openai import OpenAI
client = OpenAI(
base_url="https://carpe-diem.xyz/api/operator/v1",
api_key=os.environ["OPENAI_API_KEY"],
)
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[{"role": "user", "content": "Reply with the exact word: pong"}],
max_tokens=16,
)
print(response.choices[0].message.content)
print("model:", response.model)
print("usage:", response.usage)
.venv/bin/python hello.py
Salida obtenida:
pong
model: llama-3.3-70b
usage: CompletionUsage(completion_tokens=2, prompt_tokens=1675, total_tokens=1677, …)
Dos tokens de salida, pero 1675 de entrada por una frase de seis palabras. En nuestras dos llamadas a llama-3.3-70b con este prompt, se facturaron 1675 y luego 1695 tokens de entrada (2714 en Haiku). El origen de ese preámbulo no está documentado. max_tokens=16 limita solo la salida.
Para comprobar que un id existe antes de escribir el resto:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://carpe-diem.xyz/api/operator/v1",
api_key=os.environ["OPENAI_API_KEY"],
)
models = client.models.list()
ids = sorted(m.id for m in models.data)
print("count:", len(ids))
print("has llama-3.3-70b:", "llama-3.3-70b" in ids)
print("has claude-haiku-5-5:", "claude-haiku-5-5" in ids)
Salida: 392 identificadores, ambos True. models.list() llama a GET /v1/models con la misma clave: no hace falta un segundo cliente.
Paso 4: leer el coste de la llamada
El cuerpo JSON del SDK no lleva el precio. Carpe Diem lo pone en las cabeceras HTTP, en micro-USDC (1 USDC = 1 000 000 micro-USDC), fuera del streaming. Está documentado en la guía SDK, tabla de cabeceras X-Carpe-*. with_raw_response las expone; raw.parse() devuelve el objeto habitual.
Fichero cost.py:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://carpe-diem.xyz/api/operator/v1",
api_key=os.environ["OPENAI_API_KEY"],
)
raw = client.chat.completions.with_raw_response.create(
model="llama-3.3-70b",
messages=[{"role": "user", "content": "Reply with the exact word: pong"}],
max_tokens=16,
)
headers = raw.headers
print("x-carpe-cost-usdc-micro:", headers.get("x-carpe-cost-usdc-micro"))
print("x-carpe-input-tokens:", headers.get("x-carpe-input-tokens"))
print("x-carpe-output-tokens:", headers.get("x-carpe-output-tokens"))
print("x-carpe-available-credits:", headers.get("x-carpe-available-credits"))
print("x-carpe-cached-tokens:", headers.get("x-carpe-cached-tokens"))
response = raw.parse()
print("text:", response.choices[0].message.content)
print("usage:", response.usage)
Cabeceras leídas en esta llamada:
x-carpe-cost-usdc-micro: 524x-carpe-input-tokens: 1675x-carpe-output-tokens: 2x-carpe-available-credits: su saldo restante, en créditosx-carpe-cached-tokens: ausente (Noneen el SDK)
524 micro-USDC. A la tarifa 0,311 $ / 1,24 $ por millón de tokens (31,1 / 124 cr/M en /models, 1 crédito = 0,01 $), 1675 × 0,311 $ / M + 2 × 1,24 $ / M = 523 micro-USDC. 523 calculados, 524 cobrados: el importe parece redondeado al micro-USDC superior.
Paso 5: cambiar de modelo con una cadena
Mismo cliente, otro identificador. El catálogo público muestra los precios en créditos por millón (1 crédito = 0,01 $): llama-3.3-70b a 31,1 / 124 cr/M, claude-haiku-5-5 a 4,5 / 22,2 cr/M.

Fichero switch_model.py:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://carpe-diem.xyz/api/operator/v1",
api_key=os.environ["OPENAI_API_KEY"],
)
for model in ("llama-3.3-70b", "claude-haiku-5-5"):
raw = client.chat.completions.with_raw_response.create(
model=model,
messages=[{"role": "user", "content": "Reply with the exact word: pong"}],
max_tokens=16,
)
text = raw.parse().choices[0].message.content
print(model)
print(" text:", text)
print(" cost-usdc-micro:", raw.headers.get("x-carpe-cost-usdc-micro"))
print(" in:", raw.headers.get("x-carpe-input-tokens"), "out:", raw.headers.get("x-carpe-output-tokens"))
Ambos respondieron pong. En esta segunda ejecución, llama-3.3-70b costó 530 micro-USDC por 1695 + 2 tokens, del mismo orden que los 524 / 1675 del paso 4. A claude-haiku-5-5 se le cobraron 14 micro-USDC, con 2714 + 4 tokens en las cabeceras. A la tarifa del catálogo 4,5 / 22,2 cr/M, esos tokens darían unos 123 micro-USDC: la diferencia no está explicada (no leímos x-carpe-cached-tokens en esta llamada). El dato a retener es el de la cabecera, no el cálculo a mano.
Los identificadores se copian desde /models. llama-3.3-70b-typo no se reescribió hacia llama-3.3-70b: pegue el id de la tarjeta.
Paso 6: activar el streaming
Conserve la comprobación chunk.choices: la guía SDK la usa, y un chunk sin choices haría fallar chunk.choices[0].
import os
from openai import OpenAI
client = OpenAI(
base_url="https://carpe-diem.xyz/api/operator/v1",
api_key=os.environ["OPENAI_API_KEY"],
)
stream = client.chat.completions.create(
model="llama-3.3-70b",
messages=[{"role": "user", "content": "Write a haiku about the sea."}],
max_tokens=64,
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
print()
Texto recibido, token a token:
Crashing waves ascend
Foam kisses the sandy shore
Ocean's gentle song
En streaming, X-Carpe-Cost-Usdc-Micro no se envía (doc SDK). Para registrar el coste, quédese en la llamada sin streaming.
Si no funciona
401 AUTH_REQUIRED. Con OPENAI_API_KEY=cdm_invalid, el SDK lanzó openai.AuthenticationError: Error code: 401 - {'error': 'Unauthorized', 'code': 'AUTH_REQUIRED'}. Clave incompleta, mal copiada, o variable de entorno no exportada en esta terminal. Un export en un terminal no llega a un IDE lanzado desde el dock.
400 MODEL_ERROR. model="llama-3.3-70b-typo" devolvió: This model is no longer available upstream. Try a newer version of the same model. El mensaje habla de una retirada aguas arriba; aquí era una errata. Compruebe el id en /models o con client.models.list().
URL sin /v1. Véase el paso 2.
Ir más lejos
El mismo base_url con /v1 sustituido por /router envía la llamada al enrutador al mejor precio: misma clave, mismo cuerpo. No hemos vuelto a ejecutar hello.py sobre /router en esta prueba.
Para un agente en el terminal en lugar de un script, ya conectamos OpenCode: Kimi K3 y Claude Fable en OpenCode.
Para un modelo sin escribir hello.py, abra Create Hub, luego vuelva a pegar el id en model=.
Prueba del 22 octubre 2026 con openai==3.36.0 y una clave de prueba con saldo. Los extractos son los que se ejecutaron aquí.