API Reference

The Lucena API is fully compatible with the OpenAI API specification. Any client that works with OpenAI will work with Lucena. Just swap the base URL and your API key.

Authentication

All API requests require a Bearer token in the Authorization header. Your key is prefixed sk-lucena-.

Authorization: Bearer sk-lucena-your_key_here

Requests to /health do not require authentication. All other endpoints will return 401 Unauthorized if the key is missing or invalid.

→ Request API Access

Base URL

https://api.lucena.one

All endpoints are served over HTTPS. HTTP requests will be redirected.

EnvironmentBase URLStatus
Productionhttps://api.lucena.oneLive
Staginghttps://api-stage.lucena.oneInternal

List Models

GET /v1/models

Returns the list of available Lucena models.

Response

{
  "object": "list",
  "data": [
    {
      "id": "lucena-coder-latest",
      "object": "model",
      "owned_by": "lucena",
      "description": "Lucena Coder: advanced code generation and understanding."
    },
    {
      "id": "lucena-coder-roadrunner",
      "object": "model",
      "owned_by": "lucena",
      "description": "Lucena Coder Roadrunner: faster lower-latency coding with the same strict harness."
    },
    {
      "id": "lucena-pulse-latest",
      "object": "model",
      "owned_by": "lucena",
      "description": "Lucena Pulse: fast, general-purpose intelligence."
    }
  ]
}

Chat Completions

POST /v1/chat/completions

Creates a model response for the given conversation. Supports streaming and non-streaming modes.

Request Body

ParameterTypeDescription
model required string Model ID. Use lucena-coder-latest, lucena-coder-roadrunner, or lucena-pulse-latest.
messages required array Array of message objects with role (user | assistant | system) and content.
stream optional boolean If true, partial message deltas are sent as server-sent events. Default: false.
max_tokens optional integer Maximum tokens to generate. Default: 2048.
temperature optional float Sampling temperature between 0 and 2. Lower = more deterministic. Default: 0.7.

Non-streaming Response

{
  "id": "chatcmpl-1741912345678",
  "object": "chat.completion",
  "created": 1741912345,
  "model": "lucena-coder-latest",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Here is a binary search implementation in Python:\n\n..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 24,
    "completion_tokens": 186,
    "total_tokens": 210
  }
}

Streaming Response

When stream: true, the response is a series of text/event-stream events. Each event is a JSON object with a delta containing the new token(s). The stream ends with data: [DONE].

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant","content":"Here"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{"content":" is"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"delta":{},"finish_reason":"stop"}]}

data: [DONE]

Health Check

GET /health

Returns the current status of the API server. No authentication required. Use for uptime monitoring.

Response

{
  "status": "ok",
  "model": "coder"
}

Streaming

Lucena supports Server-Sent Events (SSE) for streaming completions. Set stream: true and handle text/event-stream in your client.

Each event is prefixed data: followed by a JSON object. The stream ends with data: [DONE]. Check for this before parsing.

JavaScript (fetch)

const response = await fetch('https://api.lucena.one/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk-lucena-your_key_here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    model: 'lucena-coder-latest',
    stream: true,
    messages: [{ role: 'user', content: 'Write a binary search in Python.' }]
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const lines = decoder.decode(value).split('\n');
  for (const line of lines) {
    if (!line.startsWith('data: ') || line === 'data: [DONE]') continue;
    const chunk = JSON.parse(line.slice(6));
    const content = chunk.choices[0]?.delta?.content || '';
    process.stdout.write(content);
  }
}

Code Examples

cURL

curl https://api.lucena.one/v1/chat/completions \
  -H "Authorization: Bearer sk-lucena-your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "lucena-coder-latest",
    "messages": [
      { "role": "user", "content": "Refactor this function to use async/await." }
    ]
  }'

Node.js (OpenAI SDK)

import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: 'sk-lucena-your_key_here',
  baseURL: 'https://api.lucena.one/v1'
});

const completion = await client.chat.completions.create({
  model: 'lucena-coder-roadrunner',
  messages: [{ role: 'user', content: 'Write a REST API in Express.' }]
});

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

Python (OpenAI SDK)

from openai import OpenAI

client = OpenAI(
    api_key="sk-lucena-your_key_here",
    base_url="https://api.lucena.one/v1"
)

completion = client.chat.completions.create(
    model="lucena-coder-latest",
    messages=[{"role": "user", "content": "Write a binary search in Python."}]
)

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

Error Handling

Lucena uses standard HTTP status codes. All error responses share the same shape.

{
  "error": {
    "message": "Invalid or missing API key.",
    "type": "authentication_error",
    "code": 401
  }
}
StatusTypeDescription
400invalid_request_errorMalformed request body or missing required fields.
401authentication_errorMissing or invalid API key.
404not_foundEndpoint does not exist.
500server_errorInference failed or internal error.