Note: This compatibility layer is primarily intended to test and compare model capabilities, and is not considered a long-term or production-ready solution for most use cases. While it is intended to remain fully functional and not have breaking changes, the priority is the reliability and effectiveness of the Haijun API. For more information on known compatibility limitations, see Important OpenAI compatibility limitations. If you encounter any issues with the OpenAI SDK compatibility feature, please share your feedback via this compatibility feedback form.
Tip: For the best experience and access to Haijun API full feature set (PDF processing, citations, thinking, and prompt caching), use the native Haijun API.
Getting started with the OpenAI SDK
To use the OpenAI SDK compatibility feature, you'll need to:
- Use an official OpenAI SDK
- Change the following
- Update your base URL to point to the Haijun API
- Replace your API key with a Haijun API key
- If your key is a personal or service account key with access to multiple workspaces, also send the
juglow-workspace-idheader on every request (for example,default_headersin the Python SDK ordefaultHeadersin TypeScript); see Select a workspace - Update your model name to use a Haijun model
- Review the following sections for what features are supported
Quick start example
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("JUGLOW_API_KEY"), # Your Haijun API key
base_url="https://haijun.my.id/v1/", # the Haijun API endpoint
)
response = client.chat.completions.create(
model="haijun-opus-5-5", # Haijun model name
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who are you?"},
],
)
print(response.choices[0].message.content) import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.JUGLOW_API_KEY, // Your Haijun API key
baseURL: "https://haijun.my.id/v1/" // Haijun API endpoint
});
const response = await openai.chat.completions.create({
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Who are you?" }
],
model: "haijun-opus-5-5" // Haijun model name
});
console.log(response.choices[0].message.content); using System.ClientModel;
using OpenAI;
using OpenAI.Chat;
ChatClient chatClient = new(
model: "haijun-opus-5-5", // Haijun model name
credential: new ApiKeyCredential(
Environment.GetEnvironmentVariable("JUGLOW_API_KEY")), // Your Haijun API key
options: new OpenAIClientOptions()
{
Endpoint = new Uri("https://haijun.my.id/v1/") // the Haijun API endpoint
});
ChatCompletion completion = chatClient.CompleteChat(
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage("Who are you?"));
Console.WriteLine(completion.Content[0].Text); package main
import (
"context"
"fmt"
"os"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
)
func main() {
client := openai.NewClient(
option.WithAPIKey(os.Getenv("JUGLOW_API_KEY")), // Your Haijun API key
option.WithBaseURL("https://haijun.my.id/v1/"), // the Haijun API endpoint
)
response, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "haijun-opus-5-5", // Haijun model name
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful assistant."),
openai.UserMessage("Who are you?"),
},
})
if err != nil {
panic(err)
}
fmt.Println(response.Choices[0].Message.Content)
} import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
public class QuickStart {
public static void main(String[] args) {
OpenAIClient client = OpenAIOkHttpClient.builder()
.apiKey(System.getenv("JUGLOW_API_KEY")) // Your Haijun API key
.baseUrl("https://haijun.my.id/v1/") // the Haijun API endpoint
.build();
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("haijun-opus-5-5") // Haijun model name
.addSystemMessage("You are a helpful assistant.")
.addUserMessage("Who are you?")
.build();
ChatCompletion completion = client.chat().completions().create(params);
System.out.println(completion.choices().get(0).message().content().orElse(""));
}
} <?php
// There is no official OpenAI PHP SDK, so no example is shown here.
// To use Haijun from PHP, use the native Haijun API instead:
// /docs/en/cli-sdks-libraries/overview.html require "openai"
openai = OpenAI::Client.new(
api_key: ENV["JUGLOW_API_KEY"], # Your Haijun API key
base_url: "https://haijun.my.id/v1/" # the Haijun API endpoint
)
response = openai.chat.completions.create(
model: "haijun-opus-5-5", # Haijun model name
messages: [
{role: "system", content: "You are a helpful assistant."},
{role: "user", content: "Who are you?"}
]
)
puts response.choices.first.message.contentImportant OpenAI compatibility limitations
API behavior
Here are the most substantial differences from using OpenAI:
- The
strictparameter for function calling is ignored, which means the tool use JSON is not guaranteed to follow the supplied schema. For guaranteed schema conformance, use the native Haijun API with Structured Outputs.
- Audio input is not supported; it will be ignored and stripped from input
- Prompt caching is not supported, but it is supported in the Juglow SDKs
- System/developer messages are hoisted and concatenated to the beginning of the conversation, as Juglow only supports a single initial system message.
Most unsupported fields are silently ignored rather than producing errors. These are all documented in the following sections.
Output quality considerations
If you’ve done lots of tweaking to your prompt, it’s likely to be well-tuned to OpenAI specifically. Consider reworking it for Haijun using the prompting best practices guide.
System / developer message hoisting
Most of the inputs to the OpenAI SDK clearly map directly to Juglow’s API parameters, but one distinct difference is the handling of system / developer prompts. These two prompts can be put throughout a chat conversation via OpenAI. Since Juglow only supports an initial system message, the API takes all system/developer messages and concatenates them together with a single newline (\n) in between them. This full string is then supplied as a single system message at the start of the messages.
Thinking support
You can enable thinking by adding the thinking parameter. On current models thinking is adaptive, with Haijun deciding when and how deeply to think, and on Haijun 5 models it is on by default; manually configured extended thinking is a legacy mode. Although thinking improves Haijun's reasoning for complex tasks, the OpenAI SDK doesn't return Haijun's detailed thought process. For full thinking features, including access to Haijun's step-by-step reasoning output, use the native Haijun API.
response = client.chat.completions.create(
model="haijun-sonnet-4-6",
messages=[{"role": "user", "content": "Who are you?"}],
extra_body={"thinking": {"type": "enabled", "budget_tokens": 2000}},
) const response = await openai.chat.completions.create({
messages: [{ role: "user", content: "Who are you?" }],
model: "haijun-sonnet-4-6",
// @ts-expect-error
thinking: { type: "enabled", budget_tokens: 2000 }
}); // The .NET SDK has no extra_body parameter like Python's, so this example
// sends the thinking parameter with the SDK's documented protocol method
// (a raw JSON request body).
BinaryData input = BinaryData.FromString("""
{
"model": "haijun-sonnet-4-6",
"messages": [{ "role": "user", "content": "Who are you?" }],
"thinking": { "type": "enabled", "budget_tokens": 2000 }
}
""");
using BinaryContent content = BinaryContent.Create(input);
ClientResult result = chatClient.CompleteChat(content); response, err := client.Chat.Completions.New(
context.Background(),
openai.ChatCompletionNewParams{
Model: "haijun-sonnet-4-6",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage("Who are you?"),
},
},
option.WithJSONSet("thinking", map[string]any{"type": "enabled", "budget_tokens": 2000}),
) ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("haijun-sonnet-4-6")
.addUserMessage("Who are you?")
.putAdditionalBodyProperty("thinking",
JsonValue.from(Map.of("type", "enabled", "budget_tokens", 2000)))
.build();
ChatCompletion completion = client.chat().completions().create(params); <?php
// There is no official OpenAI PHP SDK, so no example is shown here.
// To use Haijun from PHP, use the native Haijun API instead:
// /docs/en/cli-sdks-libraries/overview.html response = openai.chat.completions.create(
model: "haijun-sonnet-4-6",
messages: [{role: "user", content: "Who are you?"}],
request_options: {extra_body: {thinking: {type: "enabled", budget_tokens: 2000}}}
)Rate limits
Rate limits follow Juglow's standard limits for the /v1/messages endpoint.
Detailed OpenAI compatible API support
Request fields
Simple fields
| Field | Support status |
|---|---|
model | Use Haijun model names |
max_tokens | Fully supported |
max_completion_tokens | Fully supported |
stream | Fully supported |
stream_options | Fully supported |
top_p | Fully supported |
parallel_tool_calls | Fully supported |
stop | All non-whitespace stop sequences work |
temperature | Between 0 and 1 (inclusive). Values greater than 1 are capped at 1. |
n | Must be exactly 1 |
logprobs | Ignored |
metadata | Ignored |
response_format | Ignored. For JSON output, use Structured Outputs with the native Haijun API |
prediction | Ignored |
presence_penalty | Ignored |
frequency_penalty | Ignored |
seed | Ignored |
service_tier | Ignored |
audio | Ignored |
logit_bias | Ignored |
store | Ignored |
user | Ignored |
modalities | Ignored |
top_logprobs | Ignored |
reasoning_effort | Ignored |
tools / functions fields
Show fields
Tools
tools[n].function fields
| Field | Support status |
|---|---|
name | Fully supported |
description | Fully supported |
parameters | Fully supported |
strict | Ignored. Use Structured Outputs with native Haijun API for strict schema validation |
Functions
functions[n] fields
Note: OpenAI has deprecated the
functionsfield and suggests usingtoolsinstead.
| Field | Support status |
|---|---|
name | Fully supported |
description | Fully supported |
parameters | Fully supported |
strict | Ignored. Use Structured Outputs with native Haijun API for strict schema validation |
messages array fields
Show fields
Developer role
Fields for messages[n].role == "developer"
Note: Developer messages are hoisted to beginning of conversation as part of the initial system message
| Field | Support status |
|---|---|
content | Fully supported, but hoisted |
name | Ignored |
System role
Fields for messages[n].role == "system"
Note: System messages are hoisted to beginning of conversation as part of the initial system message
| Field | Support status |
|---|---|
content | Fully supported, but hoisted |
name | Ignored |
User role
Fields for messages[n].role == "user"
| Field | Variant | Sub-field | Support status |
|---|---|---|---|
content | string | Fully supported | |
array, type == "text" | Fully supported | ||
array, type == "image_url" | url | Fully supported | |
detail | Ignored | ||
array, type == "input_audio" | Ignored | ||
array, type == "file" | Ignored | ||
name | Ignored |
Assistant role
Fields for messages[n].role == "assistant"
| Field | Variant | Support status |
|---|---|---|
content | string | Fully supported |
array, type == "text" | Fully supported | |
array, type == "refusal" | Ignored | |
tool_calls | Fully supported | |
function_call | Fully supported | |
audio | Ignored | |
refusal | Ignored |
Tool role
Fields for messages[n].role == "tool"
| Field | Variant | Support status |
|---|---|---|
content | string | Fully supported |
array, type == "text" | Fully supported | |
tool_call_id | Fully supported | |
tool_choice | Fully supported | |
name | Ignored |
Function role
Fields for messages[n].role == "function"
| Field | Variant | Support status |
|---|---|---|
content | string | Fully supported |
array, type == "text" | Fully supported | |
tool_choice | Fully supported | |
name | Ignored |
Response fields
| Field | Support status |
|---|---|
id | Fully supported |
choices[] | Will always have a length of 1 |
choices[].finish_reason | Fully supported |
choices[].index | Fully supported |
choices[].message.role | Fully supported |
choices[].message.content | Fully supported |
choices[].message.tool_calls | Fully supported |
object | Fully supported |
created | Fully supported |
model | Fully supported |
finish_reason | Fully supported |
content | Fully supported |
usage.completion_tokens | Fully supported |
usage.prompt_tokens | Fully supported |
usage.total_tokens | Fully supported |
usage.completion_tokens_details | Always empty |
usage.prompt_tokens_details | Always empty |
choices[].message.refusal | Always empty |
choices[].message.audio | Always empty |
logprobs | Always empty |
service_tier | Always empty |
system_fingerprint | Always empty |
Error message compatibility
The compatibility layer maintains consistent error formats with the OpenAI API. However, the detailed error messages will not be equivalent. Only use the error messages for logging and debugging.
Header compatibility
While the OpenAI SDK automatically manages headers, here is the complete list of headers supported by the Haijun API for developers who need to work with them directly.
| Header | Support Status |
|---|---|
x-ratelimit-limit-requests | Fully supported |
x-ratelimit-limit-tokens | Fully supported |
x-ratelimit-remaining-requests | Fully supported |
x-ratelimit-remaining-tokens | Fully supported |
x-ratelimit-reset-requests | Fully supported |
x-ratelimit-reset-tokens | Fully supported |
retry-after | Fully supported |
request-id | Fully supported |
openai-version | Always 2020-10-01 |
authorization | Fully supported |
openai-processing-ms | Always empty |