We use cookies. Cookies and browser storage keep you signed in and remember your preferences. With your permission we also measure how the site is used. You can any time. See our cookie policy.

Go

SDK guides

Go

Use api14 from Go with the openai-go client, with setup, chat completion, streaming and error handling examples you can copy.

Use the official openai-go library with api14. Point option.WithBaseURL at api14 and pass any model id (for example openai/gpt-5-mini) as the model.

Install

go get github.com/openai/openai-go
export API14_API_KEY="sk-api14-..."

Configure

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/openai/openai-go"
	"github.com/openai/openai-go/option"
)

var client = openai.NewClient(
	option.WithBaseURL("https://api14.com/api/v1/"),
	option.WithAPIKey(os.Getenv("API14_API_KEY")),
)

var ctx = context.Background()

// The snippets below run inside func main().

openai.NewClient() without options reads OPENAI_BASE_URL and OPENAI_API_KEY, so you can also configure it from the environment:

export OPENAI_BASE_URL="https://api14.com/api/v1/"
export OPENAI_API_KEY="sk-api14-..."

Chat

resp, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{
	Model: "openai/gpt-5-mini",
	Messages: []openai.ChatCompletionMessageParamUnion{
		openai.UserMessage("Explain vector databases in two sentences."),
	},
})
if err != nil {
	panic(err)
}
fmt.Println(resp.Choices[0].Message.Content)

Streaming

stream := client.Chat.Completions.NewStreaming(ctx, openai.ChatCompletionNewParams{
	Model:    "anthropic/claude-sonnet-4.5",
	Messages: []openai.ChatCompletionMessageParamUnion{openai.UserMessage("Write a haiku about APIs.")},
})
for stream.Next() {
	chunk := stream.Current()
	if len(chunk.Choices) > 0 {
		fmt.Print(chunk.Choices[0].Delta.Content)
	}
}
if err := stream.Err(); err != nil {
	panic(err)
}

See Streaming.

Tool calling

params := openai.ChatCompletionNewParams{
	Model:    "openai/gpt-5-mini",
	Messages: []openai.ChatCompletionMessageParamUnion{openai.UserMessage("What's the weather in Istanbul?")},
	Tools: []openai.ChatCompletionToolParam{{
		Function: openai.FunctionDefinitionParam{
			Name:        "get_weather",
			Description: openai.String("Current weather for a city"),
			Parameters: openai.FunctionParameters{
				"type":       "object",
				"properties": map[string]any{"city": map[string]string{"type": "string"}},
				"required":   []string{"city"},
			},
		},
	}},
}

for {
	resp, err := client.Chat.Completions.New(ctx, params)
	if err != nil {
		panic(err)
	}
	msg := resp.Choices[0].Message
	if len(msg.ToolCalls) == 0 {
		fmt.Println(msg.Content)
		break
	}
	params.Messages = append(params.Messages, msg.ToParam())
	for _, call := range msg.ToolCalls {
		var args struct{ City string }
		json.Unmarshal([]byte(call.Function.Arguments), &args)
		params.Messages = append(params.Messages, openai.ToolMessage(getWeather(args.City), call.ID))
	}
}

getWeather is your function returning a string. See Tool calling.

Structured output

schema := map[string]any{
	"type": "object",
	"properties": map[string]any{
		"name": map[string]string{"type": "string"},
		"born": map[string]string{"type": "integer"},
	},
	"required":             []string{"name", "born"},
	"additionalProperties": false,
}

resp, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{
	Model:    "openai/gpt-5-mini",
	Messages: []openai.ChatCompletionMessageParamUnion{openai.UserMessage("Extract: Ada Lovelace, born 1815.")},
	ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
		OfJSONSchema: &openai.ResponseFormatJSONSchemaParam{
			JSONSchema: openai.ResponseFormatJSONSchemaJSONSchemaParam{
				Name: "person", Schema: schema, Strict: openai.Bool(true),
			},
		},
	},
})

var person struct {
	Name string `json:"name"`
	Born int    `json:"born"`
}
_ = json.Unmarshal([]byte(resp.Choices[0].Message.Content), &person)

See Structured outputs.

Image input

resp, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{
	Model: "google/gemini-2.5-flash",
	Messages: []openai.ChatCompletionMessageParamUnion{
		openai.UserMessage([]openai.ChatCompletionContentPartUnionParam{
			openai.TextContentPart("What is in this picture?"),
			openai.ImageContentPart(openai.ChatCompletionContentPartImageImageURLParam{
				URL: "https://example.com/photo.jpg", // or a data:image/png;base64,... URL
			}),
		}),
	},
})

See Vision & files.

Extra parameters

Fields the SDK has no type for, reasoning, provider, models, are added with option.WithJSONSet:

resp, err := client.Chat.Completions.New(ctx, params,
	option.WithJSONSet("reasoning", map[string]any{"effort": "high"}),
	option.WithJSONSet("provider", map[string]any{"sort": "throughput"}),
)

Embeddings

emb, err := client.Embeddings.New(ctx, openai.EmbeddingNewParams{
	Model: "openai/text-embedding-3-small",
	Input: openai.EmbeddingNewParamsInputUnion{OfArrayOfStrings: []string{"The quick brown fox", "Lorem ipsum"}},
})
if err == nil {
	fmt.Println(len(emb.Data[0].Embedding))
}

Errors

API errors are returned as *openai.Error, which carries the HTTP status, the machine Code and the raw response:

import "errors"

var apiErr *openai.Error
if errors.As(err, &apiErr) {
	switch apiErr.StatusCode {
	case 402: // insufficient_balance
		fmt.Println("Balance too low, add funds:", apiErr.Code)
	case 429: // rate_limited or daily_limit_reached
		fmt.Println("Retry after", apiErr.Response.Header.Get("Retry-After"), "s:", apiErr.Code)
	}
}

See Errors.

Timeouts and retries

The client retries 408, 409, 429 and 5xx twice by default with exponential backoff. Set the retry count and a per-attempt timeout as client or request options, and bound the whole call with a context:

client := openai.NewClient(
	option.WithBaseURL("https://api14.com/api/v1/"),
	option.WithAPIKey(os.Getenv("API14_API_KEY")),
	option.WithMaxRetries(4),
	option.WithRequestTimeout(60*time.Second), // per attempt
)

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) // all attempts
defer cancel()

Retrying does not help with daily_limit_reached or insufficient_balance. See Rate limits.

All capabilities

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api14.com/api/v1",
  apiKey: process.env.API14_API_KEY,
});

const result = await client.chat.completions.create({
  "model": "openai/gpt-5-mini",
  "messages": [
    {
      "role": "user",
      "content": "Explain vector databases in two sentences."
    }
  ]
});
console.log(result.choices[0].message.content);