SDK OpenAI Python: base_url Carpe Diem, chave cdm_, custo real

Este tutorial serve para chamar a Carpe Diem a partir de um script Python, com o SDK OpenAI que já usa: chat, lista de modelos, mudança de modelo, streaming, leitura do custo. Instala-se só um pacote, openai==3.36.0, num venv. Depois bastam dois campos: base_url para https://carpe-diem.xyz/api/operator/v1 e uma chave cdm_. O nosso ensaio de 22 de outubro de 2026 obteve pong de llama-3.3-70b por 524 micro-USDC; o mesmo cliente listou 392 modelos.

Ilustração gerada com seedream-v5-lite na Carpe Diem.
O que precisa
Nada além de Python, um venv, o SDK OpenAI fixado e uma chave Carpe Diem. Sem CLI Carpe Diem, sem SDK próprio.
- Uma conta Carpe Diem com créditos ou uma conta prepaid, e uma chave
cdm_(separador API Keys do painel do comprador). - Python 3.10 ou superior (o pacote
openai==3.36.0exige-o). pipnum venv, para fixaropenai==3.36.0.
No fim poderá: enviar um chat.completions.create (passo 3), listar identificadores via models.list() (passo 3), ler x-carpe-cost-usdc-micro (passo 4), passar de llama-3.3-70b para claude-haiku-5-5 ao mudar uma cadeia (passo 5) e fazer streaming de um haiku (passo 6).
Passo 1: criar uma chave cdm_
Abra Credits & keys, separador API Keys. As chaves começam por cdm_ e são mostradas uma só vez. Escolha como a chave paga (Credits ou Prepaid), um nome se quiser, depois Create a key.
Credits: saldo de utilização, 1 crédito = 0,01 $, sem levantamento. Prepaid: uma conta que detém; o protocolo só cobra o custo de cada chamada, levantamento possível. Ambos liquidam em USDC na Base (guia, §4.1). Uma terceira via, x402, paga a partir de uma wallet sem chave cdm_; este tutorial não a cobre.

Copie-a de imediato para um gestor de segredos: não voltará a ser mostrada. Na shell do tutorial:
export OPENAI_API_KEY=cdm_your_key_here
Para testar um modelo sem código, resta o Create Hub.
Passo 2: instalar openai 3.36.0
python3 -m venv .venv
.venv/bin/pip install openai==3.36.0
Não testámos outra versão do pacote. O cliente OpenAI envia POST /chat/completions sob base_url. Na Carpe Diem, base_url já deve incluir /v1:
https://carpe-diem.xyz/api/operator/v1
Não https://carpe-diem.xyz/api/operator: é o URL do adaptador Anthropic, outro protocolo. O guia SDK indica-o no topo da página, mesmo acima do exemplo Python OpenAI.

Passo 3: enviar a primeira mensagem
Ficheiro hello.py (o cliente é recriado aí, como em cada excerto):
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
Saída obtida:
pong
model: llama-3.3-70b
usage: CompletionUsage(completion_tokens=2, prompt_tokens=1675, total_tokens=1677, …)
Dois tokens de saída, mas 1675 de entrada por uma frase de seis palavras. Nas nossas duas chamadas a llama-3.3-70b com este prompt, foram facturados 1675 e depois 1695 tokens de entrada (2714 no Haiku). A origem deste preâmbulo não está documentada. max_tokens=16 limita só a saída.
Para verificar que um id existe antes de escrever o 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)
Saída: 392 identificadores, ambos True. models.list() chama GET /v1/models com a mesma chave: não é preciso um segundo cliente.
Passo 4: ler o custo da chamada
O corpo JSON do SDK não transporta o preço. A Carpe Diem coloca-o nos cabeçalhos HTTP, em micro-USDC (1 USDC = 1 000 000 micro-USDC), fora do streaming. Está documentado no guia SDK, tabela dos cabeçalhos X-Carpe-*. with_raw_response expõe-nos; raw.parse() devolve o objeto habitual.
Ficheiro 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)
Cabeçalhos lidos nesta chamada:
x-carpe-cost-usdc-micro: 524x-carpe-input-tokens: 1675x-carpe-output-tokens: 2x-carpe-available-credits: o seu saldo restante, em créditosx-carpe-cached-tokens: ausente (Noneno SDK)
524 micro-USDC. À tarifa 0,311 $ / 1,24 $ por milhão de tokens (31,1 / 124 cr/M em /models, 1 crédito = 0,01 $), 1675 × 0,311 $ / M + 2 × 1,24 $ / M = 523 micro-USDC. 523 calculados, 524 debitados: o montante parece arredondado para o micro-USDC superior.
Passo 5: mudar de modelo com uma string
O mesmo cliente, outro identificador. O catálogo público mostra os preços em créditos por milhão (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.

Ficheiro 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 responderam pong. Nesta segunda execução, llama-3.3-70b custou 530 micro-USDC por 1695 + 2 tokens, da mesma ordem que os 524 / 1675 do passo 4. A claude-haiku-5-5 foram debitados 14 micro-USDC, com 2714 + 4 tokens nos cabeçalhos. À tarifa do catálogo 4,5 / 22,2 cr/M, esses tokens dariam cerca de 123 micro-USDC: o desvio não está explicado (não lemos x-carpe-cached-tokens nesta chamada). O valor a reter é o do cabeçalho, não o cálculo à mão.
Os identificadores copiam-se a partir de /models. llama-3.3-70b-typo não foi reescrito para llama-3.3-70b: cole o id da ficha.
Passo 6: ligar o streaming
Mantenha o teste chunk.choices: o guia SDK usa-o, e um chunk sem choices faria falhar 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 recebido, token a token:
Crashing waves ascend
Foam kisses the sandy shore
Ocean's gentle song
Em streaming, X-Carpe-Cost-Usdc-Micro não é enviado (doc SDK). Para acompanhar o custo, fique na chamada sem streaming.
Se não funcionar
401 AUTH_REQUIRED. Com OPENAI_API_KEY=cdm_invalid, o SDK lançou openai.AuthenticationError: Error code: 401 - {'error': 'Unauthorized', 'code': 'AUTH_REQUIRED'}. Chave incompleta, mal copiada, ou variável de ambiente não exportada nesta shell. Um export num terminal não chega a um IDE aberto a partir da Dock.
400 MODEL_ERROR. model="llama-3.3-70b-typo" devolveu: This model is no longer available upstream. Try a newer version of the same model. A mensagem fala de uma retirada a montante; aqui era um erro de digitação. Verifique o id em /models ou via client.models.list().
URL sem /v1. Ver o passo 2.
Ir mais longe
O mesmo base_url com /v1 substituído por /router envia a chamada ao router ao melhor preço: a mesma chave, o mesmo corpo. Não repetimos o hello.py em /router neste teste.
Para um agente no terminal em vez de um script, já ligámos o OpenCode: Kimi K3 e Claude Fable no OpenCode.
Para um modelo sem escrever hello.py, abra o Create Hub e depois volte a colar o id em model=.
Teste de 22 outubro 2026 com openai==3.36.0 e uma chave de teste com saldo. Os excertos são os que correram aqui.