Nexforce Nexforce Router · docs Console Criar API key

Nexforce Router

Uma API de inferência compatível com OpenAI. Um endpoint e uma key despacham para Anthropic, OpenAI, Google, DeepSeek, Moonshot e Workers AI, com fallback entre modelos e controle de custo por API key.

OpenAIAnthropicGoogleDeepSeekMoonshotWorkers AI e muitos mais
import { streamText } from 'ai';
import { createOpenAI } from '@ai-sdk/openai';

const nexforce = createOpenAI({
  baseURL: 'https://router.nexforce.ai/v1',
  apiKey: process.env.NEXFORCE_API_KEY,
});

const result = streamText({
  model: nexforce('claude-3-5-sonnet'),
  prompt: 'Por que o céu é azul?',
});
from openai import OpenAI

client = OpenAI(
    base_url="https://router.nexforce.ai/v1",
    api_key="nfc_...",
)

resp = client.chat.completions.create(
    model="claude-3-5-sonnet",
    messages=[{"role": "user", "content": "Por que o céu é azul?"}],
)
print(resp.choices[0].message.content)
curl https://router.nexforce.ai/v1/chat/completions \
  -H "Authorization: Bearer nfc_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet",
    "messages": [
      { "role": "user", "content": "Por que o céu é azul?" }
    ]
  }'

Se a sua ferramenta já fala com a API da OpenAI, ela fala com o Nexforce Router. Troque a base URL e a API key, e mantenha o resto do código.

BASE https://router.nexforce.ai/v1

Compatível com o formato /v1/chat/completions da OpenAI, incluindo streaming, tools (function calling) e entrada multimodal.

Início rápido

1. Crie uma API key no Console (formato nfc_...). 2. Aponte o cliente para a base URL. 3. Chame qualquer modelo do catálogo.

curl
curl https://router.nexforce.ai/v1/chat/completions \
  -H "Authorization: Bearer $NEXFORCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet",
    "messages": [{ "role": "user", "content": "Olá!" }]
  }'
python
from openai import OpenAI

client = OpenAI(
    base_url="https://router.nexforce.ai/v1",
    api_key="nfc_...",
)

resp = client.chat.completions.create(
    model="claude-3-5-sonnet",
    messages=[{"role": "user", "content": "Olá!"}],
)
print(resp.choices[0].message.content)
typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://router.nexforce.ai/v1",
  apiKey: process.env.NEXFORCE_API_KEY,
});

const resp = await client.chat.completions.create({
  model: "claude-3-5-sonnet",
  messages: [{ role: "user", content: "Olá!" }],
});

Autenticação

Toda request autenticada usa um Bearer token no header Authorization. A key tem o prefixo nfc_ e carrega as regras de acesso (modelos permitidos, limite de custo, rate limit).

http
Authorization: Bearer nfc_suaorg_xxxxxxxxxxxxxxxx
i

A listagem de modelos (GET /v1/models) é pública e não exige key. Com uma key válida, a lista é filtrada para os modelos que aquela key pode chamar.

Modelos

Catálogo carregado ao vivo de GET /v1/models. É essa resposta que as ferramentas de código leem para popular o seletor de modelos. O preço de cada modelo fica no Console, não é exposto aqui.

GET https://router.nexforce.ai/v1/models
carregando…
IDProvedorToolsVisão
Carregando catálogo…

Chat completions

POST https://router.nexforce.ai/v1/chat/completions

O corpo segue o schema da OpenAI. O roteamento para o provedor certo é automático a partir do campo model. A resposta inclui headers X-Nexforce-Requested-Model e X-Nexforce-Served-Model para você sempre saber qual modelo respondeu.

Fallback por modelo

Quando o modelo pedido falha (sem credencial, indisponível ou erro 5xx), o router tenta os próximos modelos da cadeia configurada na key, em ordem, respeitando o allow/deny daquela key.

Parâmetros suportados

  • model — obrigatório. Id do catálogo (ex: claude-3-5-sonnet).
  • messages — obrigatório. Array no formato OpenAI (system, user, assistant, tool).
  • streamtrue para Server-Sent Events.
  • temperature, top_p, max_tokens, stop, frequency_penalty, presence_penalty.
  • tools, tool_choice — function calling (nos modelos com suporte a tools).

Streaming

Defina "stream": true para receber a resposta em chunks no formato chat.completion.chunk, idêntico à OpenAI. O encerramento é sinalizado por data: [DONE].

python
stream = client.chat.completions.create(
    model="claude-3-5-sonnet",
    messages=[{"role": "user", "content": "Conte uma história"}],
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")

Erros

Códigos HTTP padrão, com corpo JSON no formato de erro da OpenAI.

CódigoSignificado
401Key ausente ou inválida
402Saldo insuficiente — recarregue a wallet
403Modelo/provedor bloqueado para esta key, ou conta suspensa
404Modelo fora do catálogo
429Rate limit ou orçamento excedido
5xxFalha do provedor (dispara fallback quando configurado)

O corpo segue o formato de erro da OpenAI, então o tratamento dos SDKs funciona sem mudança:

python
from openai import APIStatusError

try:
    resp = client.chat.completions.create(model="claude-3-5-sonnet", messages=messages)
except APIStatusError as e:
    if e.status_code == 402:
        print("Saldo insuficiente — recarregue a wallet.")
    elif e.status_code == 429:
        print("Rate limit ou orçamento excedido.")
    else:
        print(e.status_code, e.response.text)

Mensagem de sistema

Use uma mensagem system no início do array para definir o comportamento do modelo. As demais mensagens seguem o padrão user / assistant.

curl
curl https://router.nexforce.ai/v1/chat/completions \
  -H "Authorization: Bearer $NEXFORCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet",
    "messages": [
      { "role": "system", "content": "Você é um assistente fiscal brasileiro. Responda em pt-BR, de forma objetiva." },
      { "role": "user", "content": "O que é IRRF sobre software importado?" }
    ]
  }'

Conversa multi-turno

Mantenha o histórico enviando as mensagens anteriores (user e assistant) a cada chamada. O router não guarda estado: o contexto é o array que você manda.

python
messages = [
    {"role": "system", "content": "Você é um tutor de matemática."},
    {"role": "user", "content": "Quanto é 7 x 8?"},
    {"role": "assistant", "content": "56."},
    {"role": "user", "content": "E dividido por 4?"},
]

resp = client.chat.completions.create(model="claude-3-5-sonnet", messages=messages)
messages.append({"role": "assistant", "content": resp.choices[0].message.content})

Ajustando a geração

Os parâmetros de amostragem da OpenAI são repassados ao provedor. max_tokens é aceito para todos os modelos (para a família o-series da OpenAI o router o converte para max_completion_tokens automaticamente).

json
{
  "model": "claude-3-5-sonnet",
  "messages": [{ "role": "user", "content": "Liste 3 nomes para uma cafeteria." }],
  "temperature": 0.7,
  "top_p": 0.9,
  "max_tokens": 200,
  "stop": ["\n\n"],
  "frequency_penalty": 0.3,
  "presence_penalty": 0.0
}

Function calling (tools)

Defina as funções em tools no formato da OpenAI. Quando o modelo decide chamar uma função, a resposta vem com finish_reason: "tool_calls" e os tool_calls na mensagem do assistente. Você executa a função e devolve o resultado numa mensagem role: "tool".

1. Request com a tool definida

json
{
  "model": "claude-3-5-sonnet",
  "messages": [{ "role": "user", "content": "Qual a previsão do tempo em São Paulo?" }],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Retorna o clima atual de uma cidade",
      "parameters": {
        "type": "object",
        "properties": { "city": { "type": "string" } },
        "required": ["city"]
      }
    }
  }],
  "tool_choice": "auto"
}

tool_choice aceita "auto" (padrão), "none", "required" ou { "type": "function", "function": { "name": "..." } } para forçar uma função específica.

2. Resposta do modelo (pede a função)

json
{
  "choices": [{
    "finish_reason": "tool_calls",
    "message": {
      "role": "assistant",
      "tool_calls": [{
        "id": "call_abc123",
        "type": "function",
        "function": { "name": "get_weather", "arguments": "{\"city\":\"São Paulo\"}" }
      }]
    }
  }]
}

3. Devolva o resultado da função

json
{
  "model": "claude-3-5-sonnet",
  "messages": [
    { "role": "user", "content": "Qual a previsão do tempo em São Paulo?" },
    { "role": "assistant", "tool_calls": [{ "id": "call_abc123", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"São Paulo\"}" } }] },
    { "role": "tool", "tool_call_id": "call_abc123", "content": "28°C, ensolarado" }
  ]
}

Visão (imagem)

Mande imagens no array de conteúdo com blocos image_url, no formato multimodal da OpenAI. Use um modelo com suporte a visão (a coluna "Visão" na seção Modelos indica quais).

Por URL

json
{
  "model": "claude-3-5-sonnet",
  "messages": [{
    "role": "user",
    "content": [
      { "type": "text", "text": "O que tem nesta imagem?" },
      { "type": "image_url", "image_url": { "url": "https://exemplo.com/foto.jpg" } }
    ]
  }]
}

Por base64 (data URI)

json
{ "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,/9j/4AAQSkZJRg..." } }

Documentos (PDF)

Envie um PDF como bloco file com o conteúdo em base64 em file_data. O media_type assume application/pdf quando omitido. Suportado em modelos com visão/documentos (ex: Claude).

json
{
  "model": "claude-3-5-sonnet",
  "messages": [{
    "role": "user",
    "content": [
      { "type": "text", "text": "Resuma este contrato." },
      { "type": "file", "file": {
        "filename": "contrato.pdf",
        "media_type": "application/pdf",
        "file_data": "JVBERi0xLjcKJ..."
      }}
    ]
  }]
}

Modelos open-source (Workers AI)

Os modelos com provedor workers-ai rodam direto na Cloudflare, sem precisar de chave de provedor. Use o id do catálogo normalmente; o roteamento é automático.

curl
curl https://router.nexforce.ai/v1/chat/completions \
  -H "Authorization: Bearer $NEXFORCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama-3.3-70b",
    "messages": [{ "role": "user", "content": "Escreva um haicai sobre código." }]
  }'

Atribuição de agente

Marque cada request com o nome do agente que a originou. O router registra esse rótulo no uso, então você consegue separar custo e volume por agente no Console. O nome é truncado em 120 caracteres.

Forma direta

curl
curl https://router.nexforce.ai/v1/chat/completions \
  -H "Authorization: Bearer $NEXFORCE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Nexforce-Agent: suporte-bot" \
  -d '{ "model": "claude-3-5-sonnet", "messages": [{ "role": "user", "content": "Olá!" }] }'

Nos SDKs da OpenAI, mande pelo extra_headers (Python) ou defaultHeaders (TypeScript):

python
client.chat.completions.create(
    model="claude-3-5-sonnet",
    messages=[{"role": "user", "content": "Olá!"}],
    extra_headers={"X-Nexforce-Agent": "suporte-bot"},
)

Via metadata (JSON)

Alternativa quando você já manda outros metadados. O router lê o campo agent (também aceita agent_label e _agent):

http
X-Nexforce-Metadata: {"agent": "suporte-bot"}
i

Se os dois headers vierem juntos, o X-Nexforce-Agent tem precedência sobre o agent do metadata.

Smart Routing

Quando ativado na sua configuração (no Console), o router pode trocar o modelo pedido por um equivalente mais barato antes do dispatch, preservando as capacidades necessárias (tools, visão). A troca nunca é escondida: o modelo que respondeu vem sempre nos headers de resposta, e a economia é registrada no uso.

Controle por request

Dois headers deixam você desligar ou fixar o modelo numa request específica, sobrepondo a configuração:

http
# Desliga o Smart Routing só nesta request (aceita: off, false, 0)
X-Nexforce-Smart-Routing: off

# Ou força exatamente o modelo pedido, sem substituição
X-Nexforce-Pin-Model: true
i

Esses headers só têm efeito quando o Smart Routing está habilitado na configuração. Com ele desligado, o modelo pedido é sempre o servido.

Modelo nexforce/smart-route

Em vez de escolher um modelo, aponte a request para o id nexforce/smart-route e deixe a Nexforce escolher por você. O router resolve esse id para um modelo de referência (a âncora) e, quando existe um equivalente mais barato com as mesmas capacidades (tools, visão), serve o equivalente. Quando não existe, serve a própria âncora. O modelo que de fato respondeu vem sempre nos headers de resposta.

curl
curl https://router.nexforce.ai/v1/chat/completions \
  -H "Authorization: Bearer $NEXFORCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "nexforce/smart-route",
    "messages": [{ "role": "user", "content": "Resuma este artigo em 3 tópicos." }]
  }'

É diferente do Smart Routing por configuração, que age sobre o modelo que você nomeia. O nexforce/smart-route é a própria escolha: liga o roteamento nesta request, sem precisar habilitar nada na key. O id também aparece no catálogo (/v1/models), pronto para uso em qualquer ferramenta compatível com OpenAI.

i

A resposta traz X-Nexforce-Smart-Route: true junto com o X-Nexforce-Served-Model, deixando explícito que a Nexforce escolheu o modelo por você.

Headers de resposta

Toda resposta de chat completion traz headers que dizem qual modelo realmente respondeu e quão fresca está a configuração usada.

HeaderDescrição
X-Nexforce-Requested-ModelO modelo que você pediu
X-Nexforce-Served-ModelO modelo que de fato respondeu
X-Nexforce-Substitutedtrue quando o Smart Routing trocou o modelo (ausente caso contrário)
X-Nexforce-Smart-Routetrue quando a request usou o modelo nexforce/smart-route e a Nexforce escolheu o modelo servido (ausente caso contrário)
X-Config-Synced-AtTimestamp do snapshot de configuração usado na request
curl -i
HTTP/2 200
X-Nexforce-Requested-Model: claude-3-5-sonnet
X-Nexforce-Served-Model: claude-3-5-haiku
X-Nexforce-Substituted: true
X-Config-Synced-At: 2026-06-18T11:42:07.000Z

Cursor

Em Settings → Models → OpenAI API Key, ative "Override OpenAI Base URL", cole https://router.nexforce.ai/v1 e a sua key nfc_.... O Cursor não lista modelos sozinho: adicione os ids manualmente (ex: claude-3-5-sonnet).

Cline / Roo Code

Selecione o provider OpenAI Compatible. Base URL https://router.nexforce.ai/v1, API key nfc_.... O seletor de modelos popula automaticamente a partir de /v1/models.

Continue

config.yaml
models:
  - name: Nexforce Sonnet
    provider: openai
    model: claude-3-5-sonnet
    apiBase: https://router.nexforce.ai/v1
    apiKey: nfc_...

OpenCode

opencode.json
{
  "provider": {
    "nexforce": {
      "npm": "@ai-sdk/openai-compatible",
      "options": {
        "baseURL": "https://router.nexforce.ai/v1",
        "apiKey": "nfc_..."
      }
    }
  }
}