Skip to content

Repository files navigation

🚀 Dart OpenAI

GitHub commit activityGitHub contributorsGitHub Repo starsGitHub Workflow StatusGitHub Workflow StatusGitHubPub VersionPub LikesPub PointsPub Popularity

A comprehensive Dart/Flutter client for OpenAI's powerful AI models

Quick StartDocumentationExamplesAPI CoverageContributing


✨ Overview

Dart OpenAI is an unofficial but comprehensive client package that allows developers to easily integrate OpenAI's state-of-the-art AI models into their Dart/Flutter applications. The package provides simple, intuitive methods for making requests to OpenAI's various APIs, including GPT models, DALL-E image generation, Whisper audio processing, and more.

⚠️ Note: This is an unofficial package. OpenAI does not have an official Dart library.

🎯 Key Features

  • 🚀 Easy Integration - Simple, intuitive API that mirrors OpenAI's documentation
  • 🔐 Secure Authentication - One-time setup, use anywhere in your application
  • 📡 Streaming Support - Real-time streaming for completions, chat, and fine-tune events
  • 🛠️ Developer Friendly - Comprehensive error handling and logging
  • 📚 Rich Examples - Ready-to-use examples for every implemented feature
  • 🎨 Modern UI Support - Optimized for Flutter applications
  • 🔄 Custom APIs - Additional custom endpoints for enhanced functionality

🚀 Quick Start

Installation

Add the package to your pubspec.yaml:

dependencies:
dart_openai: 

Basic Setup

import'package:dart_openai/dart_openai.dart';
voidmain() {
// Set your API keyOpenAI.apiKey ="your-api-key-here";
// Optional: Set organization IDOpenAI.organization ="your-org-id";
// Optional: Configure timeoutOpenAI.requestsTimeOut =Duration(seconds:60);
// Optional: Enable loggingOpenAI.showLogs =true;
runApp(MyApp());
}

Your First API Call

// Simple chat completionfinal chatCompletion =awaitOpenAI.instance.chat.create(
model:"gpt-3.5-turbo",
messages: [
OpenAIChatCompletionChoiceMessageModel(
role:OpenAIChatMessageRole.user,
content:"Hello, how are you?",
),
],
);
print(chatCompletion.choices.first.message.content);

📊 API Coverage (2025)

API featureStatusDetailsLast Updated
📋 Responses✅ CompleteAll11-08-2025 17:33:39
💭 Conversations✅ CompleteAll11-08-2025 17:38:56
🎵 Audio✅ CompleteAll11-08-2025 17:42:54
🎬 Videos🗓️ planned-
🎨 Images✅ CompleteAll11-08-2025 17:53:45
🎨 Images Streaaming🗓️ planned-
📊 Embeddings✅ CompleteAll11-08-2025 17:56:30
⚖️ Evals✅ CompleteAll11-08-2025 21:04:36
🔧 Fine-tuning🧩 70% Completemissing newer endpoints
📊 Graders✅ CompleteAll11-08-2025 21:46:48
📦 Batch🗓️ planned-
📁 Files✅ CompleteAll11-08-2025 21:51:34
📤 Uploads🗓️ planned-
🤖 Models✅ CompleteAll11-08-2025 21:53:13
🛡️ Moderation✅ CompleteAll11-08-2025 21:54:01
🗃️ Vector Stores✅ CompleteAll11-19-2025 12:24:15
💬 ChatKit❌ Not plannedBeta feature
📦 Containers✅ CompleteAll11-19-2025 12:24:15
🕛 Real-time🗓️ planned-
💬 Chat Completions✅ Completeexcluding stream functionality
🤖 Assistants❌ Not plannedbeta feature
🤖 Administration🗓️ planned-
📝 Completions (Legacy)✅ CompleteAll
✏️ Edits (Legacy)✅ CompleteAll

📚 Documentation

Core APIs

📋 Responses

// Create responseOpenAiResponse response =awaitOpenAI.instance.responses.create(
input:"Your input text here", model:"gpt-4",
);
// Get responseOpenAiResponse response =awaitOpenAI.instance.responses.get(
responseId:"response-id-here",
startingAfter:0, );
// Delete responseawaitOpenAI.instance.responses.delete(
responseId:"response-id-here",
);
// Cancel responseOpenAiResponse response =awaitOpenAI.instance.responses.cancel(
responseId:"response-id-here",
);
// list input itemsOpenAiResponseInputItemsList response =awaitOpenAI.instance.responses.listInputItems(
responseId:"response-id-here",
limit:10, );
// Get input token countsint inputTokens =awaitOpenAI.instance.responses.getInputTokenCounts(
model:"gpt-5",
input:"Your input text here",
);

💭 Conversations

// Create conversationOpenAIConversation conversation =awaitOpenAI.instance.conversations.create(
items: [{
"type":"message",
"role":"user",
"content":"Hello!",
}],
metadata: {
"key":"value",
"another_key":"another_value",
},
);
// Get conversationOpenAIConversation conversation =awaitOpenAI.instance.conversations.get(
conversationId:"conversation-id-here",
);
// Update conversationOpenAIConversation updatedConversation =awaitOpenAI.instance.conversations.update(
conversationId:"conversation-id",
metadata: {
"key":"new_value",
},
);
// Delete conversationawaitOpenAI.instance.conversations.delete(
conversationId:"conversation-id-here",
);
// list itemsOpenAIConversationItemsResponse itemsList =awaitOpenAI.instance.conversations.listItems(
conversationId:"conversation-id-here",
limit:10, );
// Create itemOpenAIConversationItem item =awaitOpenAI.instance.conversations.createItems(
conversationId:"conversation-id-here",
items: [
// ...
],
);
// get itemOpenAIConversationItem item =awaitOpenAI.instance.conversations.getItem(
conversationId:"conversation-id-here",
itemId:"item-id-here",
);
// delete itemawaitOpenAI.instance.conversations.deleteItem(
conversationId:"conversation-id-here",
itemId:"item-id-here",
);

🎵 Audio

// Create speechFile speechFile =awaitOpenAI.instance.audio.createSpeech(
model:"tts-1",
input:"Text to convert to speech",
voice:OpenAIAudioVoice.fable,
responseFormat:OpenAIAudioSpeechResponseFormat.mp3,
outputDirectory:"/path/to/output/directory",
outputFileName:"output_speech.mp3",
);
// Create speech as bytes (useful on web or when you do not want a temp file)Uint8List speechBytes =awaitOpenAI.instance.audio.createSpeechBytes(
model:"tts-1",
input:"Text to convert to speech",
voice:OpenAIAudioVoice.fable,
responseFormat:OpenAIAudioSpeechResponseFormat.mp3,
);
// Note: tts-1 and tts-1-hd only support alloy, ash, coral, echo, fable,// nova, onyx, sage, and shimmer. Use gpt-4o-mini-tts for newer voices// such as ballad, verse, marin, and cedar.// Transcribe audioOpenAITranscriptionGeneralModel transcription =awaitOpenAI.instance.audio.createTranscription(
model:"whisper-1",
file:File("path/to/audio.mp3"),
include: ["logprobs"],
responseFormat:OpenAIAudioResponseFormat.verbose_json,
language:"en",
prompt:"This is a sample prompt to guide transcription",
);
// Handling different transcription response formatsif (transcription isOpenAITranscriptionModel) {
print(transcription.logprobs);
print(transcription.text);
print(transcription.usage);
} elseif (transcription isOpenAITranscriptionVerboseModel) {
// print the transcription.print(transcription.text);
print(transcription.segments?.map((e) => e.end));
}
// Create Translationfinal translationText =awaitOpenAI.instance.audio.createTranslation(
file:File("path/to/audio.mp3"),
model:"whisper-1",
prompt:"use unusual english words",
responseFormat:OpenAIAudioResponseFormat.json,
);

🎬 Videos

// (To be implemented)

🎨 Images

// Generate imageOpenAIImageModel image =awaitOpenAI.instance.image.create(
model:"dall-e-3",
prompt:"image of a cat in a spaceship",
responseFormat:OpenAIImageResponseFormat.url,
size:OpenAIImageSize.size1024,
quality:OpenAIImageQuality.standard,
style:OpenAIImageStyle.vivid,
);
// Edit imageOpenAIImageModel imageEdit =awaitOpenAI.instance.image.edit(
prompt:'A fantasy landscape with mountains and a river',
image:File("path/to/image.png"),
size:OpenAIImageSize.size1024,
responseFormat:OpenAIImageResponseFormat.b64Json,
);
// Create variationList<OpenAIImageModel> imageVariation =awaitOpenAI.instance.image.variation(
model:"dall-e-2",
image:File("path/to/image.png"),
size:OpenAIImageSize.size512,
responseFormat:OpenAIImageResponseFormat.url,
);

🎨 Images Streaaming

// (To be implemented)

📊 Embeddings

OpenAIEmbeddingsModel embedding =awaitOpenAI.instance.embedding.create(
model:"text-embedding-ada-002",
input:"This is a sample text",
);

⚖️ Evals

// Create evalOpenAIEval eval =awaitOpenAI.instance.evals.create(
dataSourceConfig:RequestDatatSourceConfig.logs(),
);
// Get evalOpenAIEval eval =awaitOpenAI.instance.evals.get(
evalId:"eval-id-here",
);
// Update evalOpenAIEval updatedEval =awaitOpenAI.instance.evals.update(
evalId:"eval-id-here",
metadata: {
"key":"new_value",
},
);
// Delete evalawaitOpenAI.instance.evals.delete(
evalId:"eval-id-here",
);
// List evalsOpenAIEvalsList evalsList =awaitOpenAI.instance.evals.list(
limit:10, );
// Get eval runs.OpenAIEvalRunsList evalRuns =awaitOpenAI.instance.evals.getRuns(
evalId:"eval-id-here",
limit:3, );
// Get Eval runOpenAIEvalRun evalRun =awaitOpenAI.instance.evals.getRun(
evalId:"eval-id-here",
runId:"run-id-here",
);
// Create runOpenAIEvalRun createdRun =awaitOpenAI.instance.evals.createRun(
evalId:"eval-id-here",
dataSource:EvalRunDataSource.jsonl(),
);
// Cancel runOpenAIEvalRun canceledRun =awaitOpenAI.instance.evals.cancel(
evalId:"eval-id-here",
runId:"run-id-here",
);
// Delete runawaitOpenAI.instance.evals.deleteRun(
evalId:"eval-id-here",
runId:"run-id-here",
);
// Get output item of eval run.OpenAIEvalRunOutputItem outputItem =awaitOpenAI.instance.evals.getEvalRunOutputItem(
evalId:"eval-id-here",
runId:"run-id-here",
outputItemIdn:"item-id-here",
);
// Get eval run output items.OpenAIEvalRunOutputItemsList outputItems =awaitOpenAI.instance.evals.getEvalRunOutputItems(
evalId:"eval-id-here",
runId:"run-id-here",
limit:10,
);

🔧 Fine-tuning

// (To be implemented)

📊 Graders

// gradersfinal grader =OpenAIGraders.stringCheckGrader(...);
final grader2 =OpenAIGraders.textSimilarityGrader(...);
final grader3 =OpenAIGraders.scoreModelGrader(...);
final grader4 =OpenAIGraders.labelModelGrader(...);
final grader5 =OpenAIGraders.pythonGrader(...);
final grader6 =OpenAIGraders.multiGrader(...);
// Run graderfinal grader =awaitOpenAI.instance.graders.runGrader(
grader: grader,
modelSample:"The model output to be graded", );
// Validate Graderfinal isValid =OpenAI.instance.graders.validateGrader(
grader: grader
);

📦 Batch

// (To be implemented)

📁 Files

// Upload fileOpenAIFileModel file =awaitOpenAI.instance.files.upload(
file:File("path/to/file.jsonl"),
purpose:"assistants",
);
// List filesList<OpenAIFileModel> files =awaitOpenAI.instance.files.list(
limit:10,
);
// Retrieve fileOpenAIFileModel file =awaitOpenAI.instance.files.retrieve(
"file_id" );
// Delete fileawaitOpenAI.instance.files.delete("file-id-here");
// Retrieve file contentfinal content =awaitOpenAI.instance.files.retrieveContent(
"file_id"
);

📤 Uploads

// (To be implemented)

🤖 Models

// List all available modelsList<OpenAIModelModel> models =awaitOpenAI.instance.model.list();
// Retrieve specific modelOpenAIModelModel model =awaitOpenAI.instance.model.retrieve("gpt-3.5-turbo");
// Delete fine-tuned modelbool deleted =awaitOpenAI.instance.model.delete("fine-tuned-model-id");

🛡️ Moderation

OpenAIModerationModel moderation =awaitOpenAI.instance.moderation.create(
input: ["Text to classify for moderation"],
model:"omni-moderation-latest",
);

🗃️ Vector Stores

Vector Stores
// Create vector storeOpenAIVectorStoreModel vectorStore =awaitOpenAI.instance.vectorStores.vectorStores.create(
name:"example_vector_store",
chunkingStrategy:OpenAIVectorStoreChunkingStrategy.static(
chunkOverlapTokens:300,
maxChunkSizeTokens:750,
),
expiresAfter:OpenAIVectorStoreExpiresAfter(
anchor:"last_active_at",
days:1,
),
); // List vector storesOpenAIVectorStoreListModel allVEctorStores =awaitOpenAI.instance.vectorStores.vectorStores.list(limit:30);
// Get vector storefinal firstVectorStoreAsync =awaitOpenAI.instance.vectorStores.vectorStores.get(
vectorStoreId:"vector_store_id",
);
// Modify vector storefinal updatedVectorStore =awaitOpenAI.instance.vectorStores.vectorStores.modify(
vectorStoreId:"vector_store_id",
name:"updated_vector_store_name",
);
// Delete vector storeawaitOpenAI.instance.vectorStores.vectorStores.delete(
vectorStoreId:"vector_store_id",
);
// search in vector storefinal searchVEctorStoreResult =awaitOpenAI.instance.vectorStores.vectorStores.search(
vectorStoreId: updatedVectorStore.id,
query:"example",
maxNumResults:10,
filters:OpenAIVectorStoresSearchFilter.comparison(
type:"eq",
key:"metadata.example_key",
value:"example_value",
),
rankingOptions:OpenAIVectorStoresRankingOptions(
ranker:"none",
scoreThreshold:0,
),
);
Vector store files
// Create vector store filefinal createdVectorStoreFile =awaitOpenAI.instance.vectorStores.vectorStoresFiles.create(
vectorStoreId:"vector_store_id",
fileId:"file_id",
attributes: {
"chapter":"Chapter 1",
},
chunckingStrategy:OpenAIVectorStoreChunkingStrategy.static(
chunkOverlapTokens:300,
maxChunkSizeTokens:750,
),
);
// List vector store filesfinal vectorStoreFiles =awaitOpenAI.instance.vectorStores.vectorStoresFiles.list(
vectoreStoreId:"vector_store_id",
limit:60,
);
// Get vector store filefinal vectorStoreFile =awaitOpenAI.instance.vectorStores.vectorStoresFiles.get(
fileId:"file_id",
vectorStoreId:"vector_store_id",
);
// Get vector store file contentfinal vectorStoreFileContent =awaitOpenAI.instance.vectorStores.vectorStoresFiles.getContent(
fileId:"file_id",
vectorStoreId:"vector_store_id",
);
// Update vector store filefinal updatedVectorStoreFile =awaitOpenAI.instance.vectorStores.vectorStoresFiles.update(
fileId:"file_id",
vectorStoreId:"vector_store_id",
attributes: {
"chapter":"Updated Chapter 1",
},
);
// Delete vector store fileawaitOpenAI.instance.vectorStores.vectorStoresFiles.delete(
fileId:"file_id",
vectorStoreId:"vector_store_id",
);
Vector store file batches
// Create vector store file batchfinal vectoreStoreFileBatch =awaitOpenAI.instance.vectorStores.vectorStoreFileBatch.create(
vectorStoreId:"vector_store_id",
chunkingStrategy:OpenAIVectorStoreChunkingStrategy.static(
chunkOverlapTokens:200,
maxChunkSizeTokens:550,
),
attributes: {
"batch_name":"My First Batch",
},
fileIds: ["file-abc123", "file-def456"],
);
// Get vector store file batchfinal batch =awaitOpenAI.instance.vectorStores.vectorStoreFileBatch.get(
batchId:"batch_id",
vectorStoreId:"vector_store_id",
);
// Cancel vector store file batchfinal cancelledBatch =awaitOpenAI.instance.vectorStores.vectorStoreFileBatch.cancel(
batchId:"batch_id",
vectorStoreId:"vector_store_id",
);
// List vector store files in a batchfinal vectorStoreBatchFiles =awaitOpenAI.instance.vectorStores.vectorStoreFileBatch.list(
vectorStoreId:"vector_store_id",
batchId:'batch_id',
);

📦 Containers

Containers
// Create containerfinal container =awaitOpenAI.instance.container.containers.create(
name:"my special container",
);
// List containersfinal containers =awaitOpenAI.instance.container.containers.list(
limit:20,
);
// Get containerfinal firstContainer =awaitOpenAI.instance.container.containers.get(
containerId:"container_id",
);
// Delete containerawaitOpenAI.instance.container.containers.delete(
containerId:"container_id",
);
Container Files
// Create container filefinal containerFile =awaitOpenAI.instance.container.containerFiles.create(
file:File("path/to/file"),
containerId:"container_id",
);
// Get container filefinal gotContainerFile =awaitOpenAI.instance.container.containerFiles.get(
containerId:"container_id",
fileId:"file_id",
);
// Get container file contentfinal gotContainerFileContent =awaitOpenAI.instance.container.containerFiles.getContent(
containerId:"container_id",
fileId:"file_id",
);
// List container filesfinal allContainerFiles =awaitOpenAI.instance.container.containerFiles.list(
containerId:"container_id",
limit:20,
);
// Delete container fileawaitOpenAI.instance.container.containerFiles.delete(
fileId:"file_id",
containerId:"container_id",
);

🕛 Real-time

// (To be implemented)

💬 Chat Completions

// Basic chat completionOpenAIChatCompletionModel chat =awaitOpenAI.instance.chat.create(
model:"gpt-3.5-turbo",
messages: [
OpenAIChatCompletionChoiceMessageModel(
role:OpenAIChatMessageRole.user,
content:"Hello, how can you help me?",
),
],
temperature:0.7,
maxTokens:150,
);
// Streaming chat completionStream<OpenAIStreamChatCompletionModel> chatStream =OpenAI.instance.chat.createStream(
model:"gpt-3.5-turbo",
messages: [
OpenAIChatCompletionChoiceMessageModel(
role:OpenAIChatMessageRole.user,
content:"Tell me a story",
),
],
);
chatStream.listen((event) {
print(event.choices.first.delta.content);
});

🤖 Administration

// (To be implemented)


🔧 Configuration

Environment Variables

// Using envied package@Envied(path:".env")
abstractclassEnv {
@EnviedField(varName:'OPEN_AI_API_KEY')
staticconst apiKey =_Env.apiKey;
}
voidmain() {
OpenAI.apiKey =Env.apiKey;
runApp(MyApp());
}

Custom Configuration

voidmain() {
// Set API keyOpenAI.apiKey ="your-api-key";
// Set organization (optional)OpenAI.organization ="your-org-id";
// Set custom base URL (optional)OpenAI.baseUrl ="https://api.openai.com/v1";
// Set request timeout (optional)OpenAI.requestsTimeOut =Duration(seconds:60);
// Enable logging (optional)OpenAI.showLogs =true;
OpenAI.showResponsesLogs =true;
runApp(MyApp());
}

🚨 Error Handling

try {
final chat =awaitOpenAI.instance.chat.create(
model:"gpt-3.5-turbo",
messages: [
OpenAIChatCompletionChoiceMessageModel(
role:OpenAIChatMessageRole.user,
content:"Hello",
),
],
);
} onRequestFailedExceptioncatch (e) {
print("Request failed: ${e.message}");
print("Status code: ${e.statusCode}");
} onMissingApiKeyExceptioncatch (e) {
print("API key not set: ${e.message}");
} onUnexpectedExceptioncatch (e) {
print("Unexpected error: ${e.message}");
}

🤝 Contributing

We welcome contributions! Here's how you can help:

🐛 Bug Reports

  • Use GitHub Issues to report bugs
  • Include reproduction steps and environment details

💡 Feature Requests

  • Suggest new features via GitHub Issues
  • Check existing issues before creating new ones

🔧 Code Contributions

  • Fork the repository
  • Create a feature branch
  • Make your changes
  • Add tests if applicable
  • Submit a pull request

📚 Documentation

  • Help improve documentation
  • Add examples for missing features
  • Fix typos and improve clarity

💰 Sponsoring


📜 License

This project is licensed under the MIT License - see the LICENSE file for details.


🙏 Acknowledgments

  • OpenAI for providing the amazing AI models and APIs
  • Contributors who help maintain and improve this package
  • Sponsors who support the project financially
  • Community for feedback and suggestions

📞 Support


Made with ❤️ by the Dart OpenAI community

⭐ Star this repo🐛 Report Bug💡 Request Feature📖 Documentation

About

Dart/Flutter SDK for ChatGPT and all OpenAI APIs (GPT, Dall-e..)

Topics

Resources

Stars

666 stars

Watchers

10 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages