For Developers

Create Chat Completion

This model is part of an upcoming API update which is currently in beta and therefore subject to change.

POST https://ed.link/api/v2/openai/chat/completions

Sends a Chat Completions request through the application's configured providers. The response is the provider's Chat Completions object, plus session_id. It is not wrapped in $data.

You must provide your application secret key. This request is not made in the scope of one integration or person. X-Scope is the audit log scope: an arbitrary string, up to 128 bytes, that groups related events for retrieval. It is not sent upstream.

model must be an exact id configured on the application. Any other id is rejected. Omit model to use the application's priority list. A configured model is tried first, then the rest of the list. Each model is tried with every active key for that provider, oldest key first. A failed hop is retried only when nothing has been written to the client yet.

stream: true returns server-sent events. Any other value returns one JSON completion. The OpenAI SDK posts to {baseURL}/chat/completions. Set baseURL to https://ed.link/api/v2/openai.

session_id and context are removed before the provider call. A body scope property is forwarded and is not the X-Scope header. Every other field is forwarded, including a property this API does not document. { "hello": "world" } is sent upstream as hello. A provider can still reject a field it does not support.

Headers

HeaderRequiredDescription
AuthorizationYesBearer application secret.
Content-TypeYesapplication/json.
X-ScopeYesAudit log scope. Any string, at most 128 bytes. Not sent upstream.
X-Session-IdNoConversation id, at most 256 characters. Body session_id wins when both are set. Generated when neither is set. Returned on every response.

A blocked browser Origin returns 403.

Request Body

PropertyTypeRequiredDescription
messagesArrayYesNon-empty list of chat messages. Every system message is kept. Several system messages are merged into one. When the body is over the size cap, non-system messages are cut to the first context.head and the last context.tail.
modelStringNoExact configured model id. Omit it to use the application's priority list. Each hop sends that hop's model id.
session_idStringNoSame as X-Session-Id. The body value wins. At most 256 characters. Removed before the provider call.
contextObjectNo{ "head", "tail" } or null. head is an integer >= 0. tail is an integer >= 1 (this request's message). null disables trimming for this call. Omit it to use the application setting. Removed before the provider call.

Edlink rejects a body that is not a JSON object, an empty messages array, a missing or oversized X-Scope, an oversized session id, a context value that is not null or { "head", "tail" }, and a system message whose content is not a string when several system messages are merged. The messages kept after trimming must be at most 7,999,522 bytes.

Sample Request

const response = await axios.post(
    'https://ed.link/api/v2/openai/chat/completions',
    {
        model: 'openai/gpt-4o',
        messages: [
            { role: 'system', content: 'You are a helpful assistant.' },
            { role: 'user', content: 'What is the capital of France?' },
            { role: 'assistant', content: 'The capital of France is Paris.' },
            { role: 'user', content: 'What river runs through it?' }
        ]
    },
    {
        headers: {
            authorization: `Bearer ${application_secret_key}`,
            'x-scope': 'acme-tenant-7f3a',
            'x-session-id': 'conv_123'
        }
    }
);

The same call with the OpenAI SDK. baseURL is https://ed.link/api/v2/openai. The SDK adds /chat/completions.

import OpenAI from 'openai';

const client = new OpenAI({
    apiKey: application_secret_key,
    baseURL: 'https://ed.link/api/v2/openai',
    defaultHeaders: {
        'X-Scope': 'acme-tenant-7f3a',
        'X-Session-Id': 'conv_123'
    }
});

const completion = await client.chat.completions.create({
    model: 'openai/gpt-4o',
    messages: [
        { role: 'system', content: 'You are a helpful assistant.' },
        { role: 'user', content: 'What is the capital of France?' }
    ]
});

Set stream to true for server-sent events. Each chunk includes session_id. The stream ends with data: [DONE].

const stream = await client.chat.completions.create({
    model: 'openai/gpt-4o',
    stream: true,
    messages: [
        { role: 'system', content: 'You are a helpful assistant.' },
        { role: 'user', content: 'What is the capital of France?' }
    ]
});

for await (const chunk of stream) {
    const content = chunk.choices[0]?.delta?.content;
    if (content) {
        process.stdout.write(content);
    }
}

Sample Response

session_id is also returned in the X-Session-Id response header.

{
    "id": "chatcmpl-123",
    "object": "chat.completion",
    "created": 1677652288,
    "model": "openai/gpt-4o",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "The Seine runs through Paris."
            },
            "finish_reason": "stop"
        }
    ],
    "usage": {
        "prompt_tokens": 25,
        "completion_tokens": 10,
        "total_tokens": 35
    },
    "session_id": "conv_123"
}