Felo API PlatformFelo API Platform

Felo API (harness)

LLM API

Call Felo model endpoints through OpenAI-compatible and Anthropic-compatible protocols.

GET/api/v1/models

Authentication

Bearer API key or X-API-Key

Content type

application/json

Rate notes

Model service limits may apply. Retry with backoff on 429 or 503.

The LLM API exposes direct model calling endpoints through Felo API Platform. Use it when you want to call general-purpose language models, reuse OpenAI-compatible or Anthropic-compatible clients, or connect agent frameworks to Felo API Platform.

The LLM API currently includes three model calling surfaces:

  • POST /api/v1/responses: OpenAI Responses compatible
  • POST /api/v1/chat/completions: OpenAI Chat Completions compatible
  • POST /api/v1/messages: Anthropic Messages compatible

Planned: Decisions API

Planned; not yet available on the public API. Confirm availability before using this example.

POST https://openapi.felo.ai/api/v1/decisions

Send state and narrow typed questions to jev-1.13 (also accepted: typesafe/jev-1.13). Use /api/v1/decisions, not the Chat Completions, Messages, or Responses endpoints. Streaming is not supported.

Request fields

  • model: jev-1.13
  • state: Context to evaluate; a string or JSON value.
  • questions: Named questions using type, instructions, and criteria.
import os
import requests

response = requests.post(
    "https://openapi.felo.ai/api/v1/decisions",
    headers={"Authorization": f"Bearer {os.environ['FELO_API_KEY']}"},
    json={
        "model": "jev-1.13",
        "state": "Help! My payouts have been failing for 3 days.",
        "questions": {
            "is_urgent": {
                "type": "noul",
                "instructions": "Does this message convey urgency?",
                "criteria": {"true": "Time-sensitive", "false": "No urgency"},
            },
            "department": {
                "type": "choice",
                "instructions": "Which team should handle this?",
                "criteria": {
                    "billing": "Payments, invoicing, refunds",
                    "technical": "Bugs, outages, integrations",
                    "sales": "Pricing, upgrades, new accounts",
                },
            },
            "frustration": {
                "type": "score",
                "instructions": "How frustrated is the customer?",
                "criteria": ["Calm", "Frustrated", "Very angry"],
            },
        },
    },
    timeout=60,
)
response.raise_for_status()
answers = response.json()["answers"]
print(answers["is_urgent"]["noul"])
print(answers["department"]["choice"], answers["department"]["probabilities"])
print(answers["frustration"]["score"])

Answer types

noul: a probability from 0 to 1. choice: the selected option and its probability distribution. score: a numeric score for ordered criteria, with its distribution.

Errors use error.code (numeric HTTP status) and error.message. Handle non-2xx responses before reading answers.

Usage and pricing

The response includes usage.input_tokens, usage.output_tokens, and may include usage.cost. Reference rates checked on 2026-09-22: input USD 0.042 per million tokens; output USD 0. An output rate of zero does not make input usage free. Rates may change; use the published model price and applicable account discounts for estimates.

Authentication

LLM API requests require a Felo API Platform key. Use either Authorization: Bearer ... or X-API-Key.

Authorization: Bearer YOUR_API_KEY
X-API-Key: YOUR_API_KEY

See the Authentication Guide for details on creating and managing API keys.

Base URL

Use the public Felo API Platform host:

https://openapi.felo.ai

For SDK clients, configure the protocol-specific base URL shown in Basic Usage.

Common Headers

HeaderRequiredDescription
AuthorizationYes, unless X-API-Key is usedAPI key in the format Bearer YOUR_API_KEY
X-API-KeyYes, unless Authorization is usedAPI key alternative to the Bearer header
Content-TypeYesMust be application/json
X-Request-IdNoOptional request ID for troubleshooting

Model Discovery

The general catalog includes all model categories. Use the dedicated lists to discover video or decision models:

EndpointModel categories
GET /api/v1/modelsAll categories (unchanged)
GET /api/v1/videos/modelsVideo generation (video_generation)
GET /api/v1/decisions/modelsDecisions, including Jev (decisions)

All three endpoints accept the optional provider query parameter (for example, openrouter) and return {"object":"list","data":[...]}. Each item contains id, object, created, owned_by, and model_kind. Dedicated lists use the effective category after enabled provider mapping overrides.

Only enabled, listed, non-deleted models with current pricing matching the provider conditions are returned; a zero price is valid. Newly synchronized models are hidden until an administrator lists them. All lists share the configured ordering, with model name and ID as tie-breakers. No matches returns HTTP 200 with an empty data array. Discovery reads the local catalog and does not invoke or charge for a model call.

Only GET /api/v1/models accepts exclude_video_and_decisions (boolean, default false). Set it to true to exclude effective types video_generation and decisions; image models remain eligible. It can be combined with provider. Omitting it or setting false preserves the full catalog. Invalid boolean values return HTTP 422.

curl "https://openapi.felo.ai/api/v1/models?exclude_video_and_decisions=true&provider=openrouter" \
  -H "Authorization: Bearer ${FELO_API_KEY}"
curl "https://openapi.felo.ai/api/v1/videos/models?provider=openrouter" \
  -H "Authorization: Bearer ${FELO_API_KEY}"
curl "https://openapi.felo.ai/api/v1/decisions/models?provider=openrouter" \
  -H "Authorization: Bearer ${FELO_API_KEY}"

Choose a calling endpoint by model_kind: chat for Responses, Chat Completions, or Messages as supported by the model; video_generation for POST /api/v1/videos/generations; decisions for POST /api/v1/decisions; image_generation for POST /api/v1/images/generations. Details remain at GET /api/v1/models/{model_id}. A listed model is not necessarily compatible with every calling endpoint.

Models and Pricing

Requests use Felo API Platform's default model route. Do not send routing parameters in application requests.

Prices are listed in USD. Token rates are shown per 1 million tokens for readability; billing uses the per-token precision from the current price snapshot. Cache rates apply only when the protocol response includes cache usage. A dash means no separate published rate or published limit. Web search usage, when reported by the model service, is charged at $0.01 per search.

Model IDContextMax outputInput / 1M tokensOutput / 1M tokensCache read / 1M tokensCache write / 1M tokens
claude-haiku-4-5200K64K$1.00$5.00$0.10$1.25
claude-sonnet-4-61M128K$3.00$15.00$0.30$3.75
claude-opus-4-81M128K$5.00$25.00$0.50$6.25
claude-sonnet-51M128K$2.00$10.00$0.20$2.50
claude-haiku-5-51M128K$0.10$0.50$0.01$0.0125
gpt-5.51.05M128K$5.00$30.00$0.50-
gpt-5.5-pro1.05M128K$30.00$180.00--
gpt-5.6-luna1.05M128K$1.00$6.00$0.10$1.25
gpt-5.6-terra1.05M128K$2.50$15.00$0.25$3.125
gpt-5.6-sol1.05M128K$5.00$30.00$0.50$6.25
grok-4.5500K-$2.00$6.00$0.50-
deepseek-v4-flash1M384K$0.09$0.18$0.018-

Claude Haiku 5.5 uses tiered pricing: prompts up to 100K tokens are billed at the standard rates above, and requests whose prompt exceeds 100K tokens are billed at $0.50 input, $2.50 output, $0.05 cache read, and $0.0625 cache write per 1M tokens for the whole request.

GPT-5.6 is available in three tiers: Luna for fast, cost-efficient workloads; Terra for balanced coding, reasoning, and agentic tasks; and Sol for flagship complex reasoning and coding. Each tier also exposes a -pro model ID (gpt-5.6-luna-pro, gpt-5.6-terra-pro, and gpt-5.6-sol-pro) that uses the same underlying model with pro reasoning mode. Pricing, context length, and maximum output are unchanged for the -pro IDs.

DeepSeek V4 Flash supports reasoning and non-reasoning modes, JSON output, tool calls, Responses API, and Anthropic API compatibility. It is available through Felo's Responses, Chat Completions, and Messages surfaces. Cache write pricing is not yet published.

Basic Usage

These examples use the official OpenAI and Anthropic SDKs. Set FELO_API_KEY to your Felo API Platform key before running the examples.

export FELO_API_KEY="YOUR_API_KEY"

Install SDKs

OpenAI SDK

Use the OpenAI SDK for the Responses API and Chat Completions API.

##### JavaScript

npm install openai

##### Python

pip install openai

Anthropic SDK

Use the Anthropic SDK for the Messages API.

##### JavaScript

npm install @anthropic-ai/sdk

##### Python

pip install anthropic

Configure Clients

OpenAI-compatible endpoints use the OpenAI SDK base URL with /api/v1, because the SDK appends resource paths such as /responses and /chat/completions.

JavaScript

import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.FELO_API_KEY,
  baseURL: "https://openapi.felo.ai/api/v1",
});

Python

import os
from openai import OpenAI

openai = OpenAI(
    api_key=os.environ.get("FELO_API_KEY"),
    base_url="https://openapi.felo.ai/api/v1",
)

Anthropic-compatible endpoints use the Anthropic SDK base URL without /v1, because the SDK appends /v1/messages.

JavaScript

import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic({
  apiKey: process.env.FELO_API_KEY,
  baseURL: "https://openapi.felo.ai/api",
});

Python

import os
from anthropic import Anthropic

anthropic = Anthropic(
    api_key=os.environ.get("FELO_API_KEY"),
    base_url="https://openapi.felo.ai/api",
)

Using the Responses API

Use the Responses API for new OpenAI-compatible integrations and agent-style response objects.

JavaScript

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.FELO_API_KEY,
  baseURL: "https://openapi.felo.ai/api/v1",
});

const response = await client.responses.create({
  model: "gpt-5.6-sol",
  input: "Write a one-sentence bedtime story about a unicorn.",
});

console.log(response.output_text);

Python

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ.get("FELO_API_KEY"),
    base_url="https://openapi.felo.ai/api/v1",
)

response = client.responses.create(
    model="gpt-5.6-sol",
    input="Write a one-sentence bedtime story about a unicorn.",
)

print(response.output_text)

Using Chat Completions

Use Chat Completions when your application already sends OpenAI-style messages.

JavaScript

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.FELO_API_KEY,
  baseURL: "https://openapi.felo.ai/api/v1",
});

const completion = await client.chat.completions.create({
  model: "gpt-5.6-sol",
  messages: [
    {
      role: "user",
      content: "Give me one sentence about why API compatibility matters.",
    },
  ],
});

console.log(completion.choices[0].message.content);

Python

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ.get("FELO_API_KEY"),
    base_url="https://openapi.felo.ai/api/v1",
)

completion = client.chat.completions.create(
    model="gpt-5.6-sol",
    messages=[
        {
            "role": "user",
            "content": "Give me one sentence about why API compatibility matters.",
        }
    ],
)

print(completion.choices[0].message.content)

Using Messages

Use Messages when your client or agent framework expects Anthropic-compatible request and response shapes.

JavaScript

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: process.env.FELO_API_KEY,
  baseURL: "https://openapi.felo.ai/api",
});

const message = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 128,
  messages: [
    {
      role: "user",
      content: "Summarize the value of direct model APIs in one sentence.",
    },
  ],
});

const text = message.content
  .filter((block) => block.type === "text")
  .map((block) => block.text)
  .join("");

console.log(text);

Python

import os
from anthropic import Anthropic

client = Anthropic(
    api_key=os.environ.get("FELO_API_KEY"),
    base_url="https://openapi.felo.ai/api",
)

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=128,
    messages=[
        {
            "role": "user",
            "content": "Summarize the value of direct model APIs in one sentence.",
        }
    ],
)

text = "".join(block.text for block in message.content if block.type == "text")
print(text)

Official Documentation

For agent client setup, see Claude Code and Codex Configuration.

Protocol Reference

Responses

Use this endpoint for OpenAI Responses API compatible clients and integrations.

Endpoint

POST https://openapi.felo.ai/api/v1/responses

Request Body

ParameterTypeRequiredDescription
modelstringYesPublic Felo model ID
inputstring or arrayYesUser input, multi-turn input, or multimodal input
instructionsstringNoSystem or developer instructions
streambooleanNoWhether to use Server-Sent Events streaming
temperaturenumberNoSampling temperature
max_output_tokensintegerNoMaximum output tokens

SDK Request

const response = await client.responses.create({
  model: "gpt-5.6-sol",
  input: "Reply with exactly: responses ok",
});

console.log(response.output_text);

Response Text Path

output_text

Chat Completions

Use this endpoint for OpenAI Chat Completions compatible clients and SDKs.

Endpoint

POST https://openapi.felo.ai/api/v1/chat/completions

Request Body

ParameterTypeRequiredDescription
modelstringYesPublic Felo model ID
messagesarrayYesConversation messages
messages[].rolestringYessystem, user, or assistant
messages[].contentstringYesMessage content
streambooleanNoWhether to use Server-Sent Events streaming
temperaturenumberNoSampling temperature
max_tokensintegerNoMaximum output tokens

SDK Request

const completion = await client.chat.completions.create({
  model: "gpt-5.6-sol",
  messages: [
    {
      role: "user",
      content: "Reply with exactly: chat completions ok",
    },
  ],
});

console.log(completion.choices[0].message.content);

Response Text Path

choices[0].message.content

Messages

Use this endpoint for Anthropic Messages compatible clients and SDKs.

Endpoint

POST https://openapi.felo.ai/api/v1/messages

Request Body

ParameterTypeRequiredDescription
modelstringYesPublic Felo model ID
max_tokensintegerYesMaximum output tokens
messagesarrayYesConversation messages
messages[].rolestringYesuser or assistant
messages[].contentstring or arrayYesPlain text or Anthropic content blocks
systemstringNoSystem prompt
streambooleanNoWhether to use Server-Sent Events streaming
temperaturenumberNoSampling temperature

SDK Request

const message = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 64,
  messages: [
    {
      role: "user",
      content: "Reply with exactly: messages ok",
    },
  ],
});

const text = message.content
  .filter((block) => block.type === "text")
  .map((block) => block.text)
  .join("");

console.log(text);

Content Block Request

const message = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 64,
  messages: [
    {
      role: "user",
      content: [
        {
          type: "text",
          text: "Reply with exactly: messages ok",
        },
      ],
    },
  ],
});

Response Text Path

content[].text

Streaming

Set stream to true to receive Server-Sent Events. The event payload format follows the selected protocol:

  • Responses streams return Responses-compatible response events.
  • Chat Completions streams return OpenAI-compatible chat completion chunks.
  • Messages streams return Anthropic-compatible message events.
const stream = await client.responses.create({
  model: "gpt-5.6-sol",
  input: "Write one sentence.",
  stream: true,
});

Clients should parse the stream according to the protocol they are using rather than expecting one shared event schema across all three endpoints.

Errors

The LLM API returns the error shape of the selected protocol whenever possible. Common causes include:

HTTP StatusCauseSuggested Action
400Invalid JSON body or missing required protocol fieldsCheck model, messages, input, max_tokens, and content block fields
401Missing or invalid API keyVerify Authorization: Bearer ... or X-API-Key
402Insufficient account creditsCheck your Felo account balance
429Rate limit exceededSlow down requests and retry later
502Model service request failedRetry and provide X-Request-Id when contacting support
503Model service temporarily unavailableRetry with backoff or choose another published model