openai_dart 12.0.0
openai_dart: ^12.0.0 copied to clipboard
Dart client for the OpenAI REST APIs and realtime WebSocket/WebRTC workflows with type-safe access to GPT, image, audio, and Responses APIs.
OpenAI Dart Client #
Dart and Flutter client for the OpenAI API. Generate text with the Responses API, stream output, call tools, and work with images, audio, and embeddings.
Tip
Coding agents: start with llms.txt for documentation and examples.
Table of Contents
Features #
- Responses API: text generation, streaming, conversations, structured output, vision, and tool calling.
- Chat Completions, Decisions, embeddings, and image and audio generation.
- Built-in web search, file search, Code Interpreter, computer use, and custom tools.
- Files, batches, fine-tuning, signed webhooks, and safety resources.
- Realtime and Live sessions, persistent Responses WebSockets, Agents, and Vaults.
- Pure Dart support for Dart and Flutter on mobile, desktop, web, and servers.
Why choose this client? #
- Use typed Dart requests and responses with a resource API similar to the official SDKs.
- Use the same client in Dart backends and Flutter apps, without a Flutter dependency.
- Get streaming helpers, configurable retries, interceptors, and typed exceptions.
- Rely on strict semver and migration guides when upgrading.
Quickstart #
Requires Dart 3.12 or later and works with Dart and Flutter. Set OPENAI_API_KEY in your environment before running this native Dart example. For upgrades, see the Migration Guide.
dependencies:
openai_dart: ^12.0.0
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.responses.create(
const CreateResponseRequest(
model: 'gpt-5.5',
input: ResponseInput.text('What is the capital of France?'),
),
);
print(response.outputText);
} finally {
client.close();
}
}
Keep API keys on trusted infrastructure. For a distributed Flutter or web app, route requests through your backend.
Configuration #
API keys, environment variables, and client lifetime
OpenAIClient.fromEnvironment() reads OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_ORG_ID, and OPENAI_PROJECT_ID. It also reads optional OPENAI_WEBHOOK_SECRET for local verification. Environment loading is for native Dart; use explicit configuration when environment variables are unavailable.
OpenAIClient.withApiKey('YOUR_API_KEY') creates a client from a supplied key. Reuse a client for multiple requests and call close() when finished; an injected HTTP client remains caller-owned.
Timeouts, retries, and custom endpoints
Use OpenAIConfig for a proxy, timeout, retry policy, or organization/project selection.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient(
config: OpenAIConfig(
authProvider: ApiKeyProvider('YOUR_API_KEY'),
baseUrl: 'https://api.openai.com/v1',
timeout: const Duration(minutes: 10),
connectTimeout: const Duration(seconds: 30),
retryPolicy: const RetryPolicy(maxRetries: 3),
// organization: 'org-...',
// project: 'proj-...',
),
);
try {
final response = await client.responses.create(
const CreateResponseRequest(
model: 'gpt-5.5',
input: ResponseInput.text('Hello!'),
),
);
print(response.outputText);
} finally {
client.close();
}
}
For Azure, set the deployment URL and use AzureApiKeyProvider. See Error Handling for retry boundaries.
Update configuration and rotate credentials
Use client.updateConfig(...) or client.updateAuthProvider(...), then acquire a fresh resource handle. Previously obtained handles keep their original configuration, including child resources, retries, streams, and WebSocket recovery. An update shares the existing HTTP pool and leaves active work running.
client.updateConfig(
authProvider: ApiKeyProvider('NEW_API_KEY'),
timeout: const Duration(seconds: 60),
organization: null, // Explicit null clears this optional setting.
);
final responses = client.responses; // Uses the updated settings.
Omitted options retain their values; defaultHeaders: {} clears global headers. Header maps are copied. For credential rotation used by retained handles, supply an AuthProvider that returns a fresh map for each request. Providers and custom interceptors keep their application-owned state. Logging body policy follows the handle; the package logger's filtering level remains shared.
Imports for Realtime and retained Assistants types
The main import is package:openai_dart/openai_dart.dart. Realtime uses package:openai_dart/openai_dart_realtime.dart. Retained Assistants types use package:openai_dart/openai_dart_assistants.dart; that API shut down on August 26, 2026. See the Responses migration guide.
How do I use Responses through Google Vertex?
Inject a Google token callback; your application owns credential refresh/caching. The provider acquires a token for each HTTP attempt, including retries.
final provider = VertexProvider(
project: 'my-google-project',
location: 'global',
tokenProvider: () async => googleCredentials.accessToken(),
);
final client = OpenAIClient(config: OpenAIConfig.vertex(provider: provider));
Use the regular client.responses create, retrieve, cancel, delete, input-items
and compact methods, plus createStream for SSE. A complete baseUrl on
VertexProvider can replace project/location for a trusted proxy. Other resources,
Responses listing/token counting and WebSockets are unsupported and fail locally.
Do not supply OpenAI auth, organization/project or custom auth headers.
The request timeout includes token acquisition and response headers; buffered HTTP
also retains its normal body timeout. SSE has no whole-stream deadline: use an
abort trigger or cancel its subscription. Late timed-out/aborted token results
cannot dispatch a request; the application still owns cancellation of any work
inside its callback. Redirect following is disabled. Closing the client promptly aborts provider work,
including unresolved token waits, while callback-owned work remains application-owned.
Borrowed HTTP pools remain
caller-owned; a dedicated stream factory retains its normal close-on-completion
policy. Provider updates use updateConfig(vertexProvider: replacement) and the
same retained-resource snapshot rules described above.
The portable callback path uses no Google dependency or automatic ADC discovery.
VertexProvider.fromEnvironment reads Google project/location on native Dart and
still requires an injected callback. Browser/Wasm use explicit routing; endpoint
CORS, access permissions and model availability remain service-controlled.
How do I select an OpenAI regional endpoint?
final client = OpenAIClient(
config: OpenAIConfig.forDataResidency(
OpenAIDataResidency.eu,
authProvider: ApiKeyProvider(euProjectApiKey),
),
);
The named SDK mapping supports global, us, eu and ae. US/EU support eligible
regional processing; UAE processing is limited to supported model/service
combinations. The official guide also lists storage-only regional endpoints
(Australia, Canada, Japan, India, Singapore, South Korea and the UK); select their
complete root through ordinary OpenAIConfig(baseUrl: ...) when applicable.
Regional storage does not imply regional processing. A matching project, approved
account settings and eligible models/features are still required; endpoint or
credential selection alone provides no residency guarantee. Google Vertex
locations are a separate provider setting.
Usage #
Start with the Responses API for a model call and its output. Expand a topic for a short example or a link to a complete workflow.
Responses API #
How do I create a response?
Call client.responses.create with a model and input. Read the generated text with response.outputText and token usage with response.usage.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.responses.create(
const CreateResponseRequest(
model: 'gpt-5.5',
input: ResponseInput.text('What is the capital of France?'),
),
);
print(response.outputText);
} finally {
client.close();
}
}
How do I stream responses?
Use client.responses.createStream and textDeltas() to display text as it arrives. Use the typed events or accumulate() when you also need tool calls and response metadata; collectText() consumes the stream into one string.
import 'dart:io';
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final stream = client.responses.createStream(
const CreateResponseRequest(
model: 'gpt-5.5',
input: ResponseInput.text('Tell me a short story.'),
),
);
await for (final text in stream.textDeltas()) {
stdout.write(text);
}
} finally {
client.close();
}
}
How do I continue a conversation?
Pass the previous response ID with the next input. For separately managed conversation history, use client.conversations.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final first = await client.responses.create(
const CreateResponseRequest(
model: 'gpt-5.5',
input: ResponseInput.text('My name is Alice.'),
),
);
final next = await client.responses.create(
CreateResponseRequest(
model: 'gpt-5.5',
previousResponseId: first.id,
input: const ResponseInput.text('What is my name?'),
),
);
print(next.outputText);
} finally {
client.close();
}
}
How do I get structured JSON output?
Set TextConfig.format to JsonSchemaFormat to request output matching your schema. Check for refusals and incomplete responses before decoding the text.
import 'dart:convert';
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.responses.create(
const CreateResponseRequest(
model: 'gpt-5.5',
input: ResponseInput.text('Extract the name from: Alice is a doctor.'),
text: TextConfig(
format: JsonSchemaFormat(
name: 'person',
strict: true,
schema: {
'type': 'object',
'properties': {
'name': {'type': 'string'},
},
'required': ['name'],
'additionalProperties': false,
},
),
),
),
);
if (response.status == ResponseStatus.completed &&
response.outputText.isNotEmpty) {
print(jsonDecode(response.outputText));
}
} finally {
client.close();
}
}
How do I use tool calling?
Define a function with JSON Schema parameters. Your application executes the requested function and returns its result with the original callId; the client does not execute tools for you.
import 'dart:convert';
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.responses.create(
CreateResponseRequest(
model: 'gpt-5.5',
input: const ResponseInput.text(
'Use the add tool to calculate 123 + 456.',
),
tools: [
ResponseTool.function(
name: 'add',
description: 'Add two numbers',
parameters: {
'type': 'object',
'properties': {
'a': {'type': 'number'},
'b': {'type': 'number'},
},
'required': ['a', 'b'],
'additionalProperties': false,
},
),
],
),
);
final results = <Item>[];
for (final call in response.functionCalls) {
if (call.name != 'add') throw StateError('Unknown tool: ${call.name}');
final args = jsonDecode(call.arguments) as Map<String, dynamic>;
final sum = (args['a'] as num) + (args['b'] as num);
results.add(
FunctionCallOutputItem.string(
callId: call.callId,
output: sum.toString(),
),
);
}
if (results.isNotEmpty) {
final finalResponse = await client.responses.create(
CreateResponseRequest(
model: 'gpt-5.5',
previousResponseId: response.id,
input: ResponseInput.items(results),
),
);
print(finalResponse.outputText);
} else {
print(response.outputText);
}
} finally {
client.close();
}
}
How do I analyze images?
Include text and image content in a Responses input message. Images can be supplied as a public URL, a data URL, or an uploaded file ID.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.responses.create(
const CreateResponseRequest(
model: 'gpt-5.5',
input: ResponseInput.items([
MessageItem(
role: MessageRole.user,
content: [
InputContent.text('What is in this image?'),
InputContent.imageUrl('https://example.com/image.jpg'),
],
),
]),
),
);
print(response.outputText);
} finally {
client.close();
}
}
How do I search the web?
Add ResponseTool.webSearch() to let the model search for current information. The full examples also show location hints, domain filters, sources, and image results.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.responses.create(
CreateResponseRequest(
model: 'gpt-5.5',
input: const ResponseInput.text(
'What are the latest developments in AI?',
),
tools: [ResponseTool.webSearch()],
),
);
print(response.outputText);
} finally {
client.close();
}
}
How do I count input tokens?
Use client.responses.inputTokens.count to estimate input size before generating a response.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final count = await client.responses.inputTokens.count(
model: 'gpt-5.5',
input: const ResponseInput.text('Hello, how are you?'),
);
print(count.inputTokens);
} finally {
client.close();
}
}
Which model IDs and account settings can I use?
Model IDs are open strings, including gpt-6.1-terra. GPT-6 Rosalind requires trusted access for authorized internal research; an ID does not grant access. See the model catalog and API changelog.
Paid usage tiers Build, Launch, and Grow, project service-tier permissions, and subscription API credits are managed by OpenAI. They are separate from a request's serviceTier. Review rate limits and credit eligibility; the client does not change account entitlements.
Other model APIs #
How do I use chat completions?
Use client.chat.completions.create for applications built around Chat messages. Read the first choice with response.text; new applications can start with the Responses examples above.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.chat.completions.create(
ChatCompletionCreateRequest(
model: 'gpt-5.5',
messages: [
ChatMessage.system('You are a helpful assistant.'),
ChatMessage.user('What is the capital of France?'),
],
),
);
print(response.text);
} finally {
client.close();
}
}
How do I stream chat completions?
Use client.chat.completions.createStream with textDeltas() or ChatStreamAccumulator. Set StreamOptions(includeUsage: true) for final usage; the usage-only chunk can have no choices.
How do I classify or score shared input?
Use client.decisions.create for typed predicate, choice, and score questions. Answers can include refusals. Shared input supports text, JSON, images, and conversation/tool history; each request accepts up to 400 questions. Use DecisionInstructions.parts with the *WithInstructions question factories for question-specific text, images, and JSON. Optional cache controls apply to shared input only; Decisions supports a 30m TTL.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final decision = await client.decisions.create(
DecisionRequest(
model: 'gpt-6-luna',
input: DecisionInput.text('The screen arrived broken.'),
questions: [
DecisionQuestion.predicate(
name: 'damaged',
instructions: 'Does the customer report a damaged item?',
),
],
),
);
for (final answer in decision.answers) {
if (answer case PredicateDecisionAnswer(:final probability)) {
print('Damage probability: $probability');
} else if (answer is RefusalDecisionAnswer) {
print('The question was refused.');
}
}
} finally {
client.close();
}
}
→ Full example · GA inputs and caching (offline) · Image input example
How do I create embeddings?
Use client.embeddings.create to generate text vectors. Set dimensions when you need a smaller vector.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.embeddings.create(
EmbeddingRequest(
model: 'text-embedding-3-small',
input: EmbeddingInput.text('Hello, world!'),
dimensions: 256,
),
);
print(response.firstEmbedding);
} finally {
client.close();
}
}
Images and audio #
How do I generate and edit images with GPT Image 2.5?
Use client.images.generate or edit with an explicit model. Use editJson for URL, data URL, or file-ID inputs; generation and editing also have streaming variants.
import 'dart:convert';
import 'dart:io';
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final response = await client.images.generate(
const ImageGenerationRequest(
model: ImageModels.gptImage25Flare,
prompt: 'A cute robot holding a flower',
size: ImageSize.size1024x1024,
),
);
final image = response.data.first.b64Json;
if (image != null) {
await File('robot.png').writeAsBytes(base64Decode(image));
}
} finally {
client.close();
}
}
GPT Image 1 retired on October 23, 2026. Older gpt-image-1.5, gpt-image-1-mini and chatgpt-image-latest retire on December 1; use Sunburst or Flare. See the deprecation schedule.
How do I guide an image edit with markup?
Set ImageEditRequest.markup to PNG bytes for multipart uploads, or ImageEditJsonRequest.markup to an ImageReference for JSON edits. The overlay must include transparent pixels and match the first input image's dimensions after orientation. Markup and mask are mutually exclusive; the service validates image contents and model support.
Pass a stable, privacy-preserving safetyIdentifier of at most 128 characters on each image request. A nonempty identifier takes precedence over deprecated user; omission, null, or an empty string leaves that fallback to the service. Ordinary responses and completed image events expose the effective identifier.
Responses image-tool calls retain ImageGenerationCallStatus.failed/.generating and optional error.moderationDetails, including the stage and public categories. Use supported explicit image models; gpt-image-1 shut down October 23, 2026.
How do I use audio?
Use client.audio.speech.create for speech bytes, createByteStream for audio chunks, and createStream for typed speech events. Transcription and translation are available through client.audio.transcriptions and client.audio.translations.
import 'dart:io';
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final bytes = await client.audio.speech.create(
const SpeechRequest(
model: 'gpt-4o-mini-tts',
input: 'Hello! How are you today?',
voice: SpeechVoice.marin,
responseFormat: SpeechResponseFormat.mp3,
),
);
await File('speech.mp3').writeAsBytes(bytes);
} finally {
client.close();
}
}
→ Full example · Streaming speech · Transcription and translation
How do I generate, replay, and stream Chat audio?
Request Chat audio through client.chat.completions and choose a built-in or custom voice. Replay the returned audio ID in later messages; accumulate streamed audio before decoding it.
How do I manage voice consent recordings?
Use client.audio.voiceConsents to upload and manage consent recordings before creating custom voices.
How do I create a custom voice?
Create a saved voice with PromptVoiceCreateRequest(name: ..., prompt: ...), then select its ID with LiveVoice.custom(id: voice.id) at Live startup. Prompt voices work only in Live. Delete a saved voice explicitly with client.audio.voices.delete(voice.id).
For a recording-based voice, keep using CustomVoiceCreateRequest with a consent ID and audio sample. Prompt requests default to JSON; set encoding: VoiceCreateEncoding.multipart when needed.
→ Prompt create/use/delete example · Consented sample example
Files, batches, and model evaluation #
How do I manage files?
Use client.files to upload, list, retrieve, and delete files. Use client.uploads for large multipart uploads.
import 'dart:io';
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final file = await client.files.upload(
bytes: await File('training.jsonl').readAsBytes(),
filename: 'training.jsonl',
purpose: FilePurpose.fineTune,
);
print(file.id);
} finally {
client.close();
}
}
How do I use batch processing?
Use client.batches.create to submit a JSONL input file for asynchronous processing. Retrieve the batch status and output file when it completes.
How do I fine-tune a model?
Create a job through client.fineTuning.jobs with a training file ID, then retrieve its status and resulting model name.
Webhooks and safety #
How do I receive signed webhooks?
Verify the original request bytes and headers with WebhookVerifier.unwrapBytes before reading an event. WebhookVerifier.fromEnvironment() reads OPENAI_WEBHOOK_SECRET without an API key; handle invalid signatures, acknowledge receipt, and deduplicate deliveries in your receiver.
Environment notifications are typed for agent.environment.ready, failed, suspended and expired. Subscribe with the corresponding WebhookEventType.agentEnvironment* choices, verify the original delivery bytes, and retrieve the environment using the typed payload’s id. Ready/failed concern prewarm setup; suspended may resume from a snapshot, while expired cannot. Receivers own acknowledgment and deduplication.
How do I manage webhook endpoints?
Use client.webhooks to create, list, update, delete, rotate, and test project endpoints, and client.webhooks.eventTypes.list() to discover webhook event types. Save signing secrets returned by creation or rotation securely; test sends a real delivery.
How do I moderate content?
Use client.moderations.create to check text against content policies.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final result = await client.moderations.create(
ModerationRequest(input: ModerationInput.text('Check this text')),
);
print(result.results.first.flagged);
} finally {
client.close();
}
}
How do I investigate verified safety notifications?
Use client.safety.alerts for project alerts and client.safety.cases for organization cases. Retrieve IDs from verified notices using credentials for the correct scope.
How do I inspect monitoring failures?
Inspect typed monitoring details on HTTP exceptions, failed Responses, and WebSocket errors. These details describe the failure; they do not automatically resume work or execute suggested actions.
How do I check content provenance?
Use client.contentProvenanceChecks.create to inspect an image or audio file for C2PA and SynthID signals. Dispatch on the returned result type.
Advanced Responses workflows #
How do I use persistent Responses WebSockets?
Use client.responses.connect() for persistent requests. Add an opt-in session to route parallel lanes and collect final responses within explicit local budgets. Browser connections require an authenticated backend proxy because WebSockets cannot send API-key headers.
final connection = await client.responses.connect();
final session = ResponsesWebSocketSession(
connection,
limits: const ResponsesWebSocketLimits(
maxLanes: 4,
maxEventsPerLane: 1024,
maxEvents: 2048,
maxBytesPerLane: 4 * 1024 * 1024,
maxBytes: 8 * 1024 * 1024,
maxResponseBytes: 8 * 1024 * 1024,
),
);
try {
final planner = session.lane('planner');
planner.create(const CreateResponseRequest(
model: 'gpt-6-sol',
input: ResponseInput.text('Prepare the planner context.'),
), generate: false);
final warmup = await planner.getFinalResponse();
planner.create(CreateResponseRequest(
model: 'gpt-6-sol',
previousResponseId: warmup.id,
input: const ResponseInput.text('Draft a short plan.'),
));
final response = await planner.getFinalResponse();
print(response.outputText);
} finally {
await session.close(); // Detaches the helper.
await connection.close();
}
streamId routes a lane; previousResponseId selects conversation history. getFinalResponse() also returns failed/incomplete responses, so inspect status. Use lane.receive() for individual events. Cancel a wait with abortTrigger and resume on the same lane; lane.close() releases its retained state. Detached IDs remain reserved on that connection. Session helpers currently require recovery to be disabled.
To change output format mid-session, include ConfigurationUpdateItem(text: ConfigurationUpdateText(format: JsonSchemaFormat(...))) in the next request's input. Use const ConfigurationUpdateText.plainText() to reset; omitting text leaves it alone. JSON object mode and explicit null updates are unsupported.
→ Offline session example: manual tool continuation, fork barrier, and compacted-history replay. Low-level example retains direct connection use.
How do I steer a running Responses request?
Use the steering controls to submit input during an active response. Respect pending continuation state so accepted input and completed tool results are not sent twice.
How do I recover a Responses WebSocket?
Opt into connection recovery and handle queued or unsent requests explicitly. Recovery reconnects the transport without automatically replaying frames already sent to the server.
How do I use async function and custom tools?
Declare async tools and return results with their original call IDs. Continue from the latest response ID when concurrent jobs complete. Use ResponseToolChoice.custom(name: 'my_tool') to select a declared custom tool.
How do I return client-discovered tools?
Return complete discovered function or custom-tool definitions with the original tool-search call ID. The example shows discovery and continuation without executing the tools.
How do I filter web search and inspect image results?
Configure domain and content-type filters on ResponseTool.webSearch and request sources or image results. Search output is available through both ordinary Responses and streamed events.
How do I replay reasoning across tool calls?
Convert completed reasoning output with ReasoningItem.toInput() and keep it in the original history order. For a reasoning/function-call turn:
final history = <Item>[...previousInput];
for (final item in response.output) {
history.add(switch (item) {
final ReasoningItem reasoning => reasoning.toInput(),
final FunctionCallOutputItemResponse call => call.toFunctionCallItem(),
_ => throw StateError('Handle this output kind before replaying it.'),
});
}
// After your application executes the requested tool:
history.add(FunctionCallOutputItem.string(
callId: callId,
output: toolResult,
));
final next = await client.responses.create(CreateResponseRequest(
model: model,
input: ResponseInput.items(history),
));
ReasoningInputItem also supports direct construction and Item.fromJson(), with required id and summary. It keeps plaintext content, summaries, opaque encrypted state, status and beta agent metadata separate from assistant text. Use finalized streaming items; an added item's encrypted state may be unfinished.
Provider support differs: DeepSeek supports plaintext reasoning input but does not support summaries or encrypted reasoning. Raw ResponseInput.fromOutputItems(...) remains available for provider-specific shapes. This helper preserves returned data; it does not generate or interpret reasoning.
How do I change reasoning effort during a conversation?
Insert a ConfigurationUpdateItem before the next user input to change subsequent reasoning effort while preserving the request-level baseline. The full example covers replay and the supported compaction boundaries.
How do I prewarm the prompt cache and inspect diagnostics?
Use ResponsePromptCacheOptionsParam for Responses prewarming, TTL, and comparison diagnostics. Chat uses the narrower PromptCacheOptionsParam; returned usage counters report actual cached tokens.
Set PromptCacheBreakpointConfig(ttl: PromptCacheBreakpointTtl.hours12) on stable shared content for a 12-hour boundary. Omit ttl to inherit the request. The pinned top-level PromptCacheTtl still permits only 30m; Decisions uses separate cache controls.
Read response.toolUsage separately from response.usage for hosted image-generation tokens and billable web searches. Missing tool usage or cached counts mean unknown, not zero.
How do I configure an execution container?
Use client.containers to create a container with a memory tier and network policy, then pass its ID to Code Interpreter. See the migration guide for v11 configuration changes.
How do I configure hosted shell and return local results?
Configure a hosted shell through Responses tools, or execute local commands in your application and return their outputs. The client does not run local shell commands automatically.
How do I observe compaction progress?
Watch typed compaction events in the Responses stream. Progress events are nonterminal; preserve the complete returned compacted output for continuation.
How do I select and inspect an access program?
Set access-program options explicitly when your account is eligible, and inspect the effective program returned by the service. Selection does not provision access or change account eligibility.
How do I inject multi-agent tool results?
Use beta multi-agent injection to return tool results to the owning agent. Track acknowledgments and uncommitted results explicitly rather than rerunning tools after uncertain delivery.
Live and Realtime #
How do I use the Realtime API?
Import openai_dart_realtime.dart for Realtime WebSocket and WebRTC sessions with audio events. Use client.realtimeSessions for ephemeral client secrets and WebRTC calls; your application owns capture, playback, and peer-connection setup.
import 'dart:io';
import 'package:openai_dart/openai_dart_realtime.dart' as realtime;
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final session = await client.realtime.connect(model: 'gpt-realtime-2.1');
try {
session.sendUserMessage('Say hello.', createResponse: false);
session.createResponse(outputModalities: ['text']);
await for (final event in session.events) {
if (event is realtime.ResponseTextDeltaEvent) {
stdout.write(event.delta);
} else if (event is realtime.ResponseDoneEvent) {
break;
} else if (event is realtime.ErrorEvent) {
throw StateError(event.error.message);
}
}
} finally {
await session.close();
}
} finally {
client.close();
}
}
How do I select Realtime response input and noise strength?
Pass RealtimeResponseInputItem values to connection.createResponse(input: ...) to reference existing items or supply typed message/function-call history. Setting input creates a context for that response; input: [] clears its context. References use existing server item IDs. Set conversation: 'none' to keep the response output out of the default conversation.
Set AudioInputNoiseReduction.strength between 0 and 1. Omit strength on an update to preserve the current value; clearing the wrapper's noise reduction disables filtering. Use RealtimeAudioConfigOutput.voiceSelection for an audio-sample custom voice, or keep voice for a named voice. Prompt-generated custom voices support Live only.
How do I stream Realtime translation?
Use client.realtime.connectTranslation(model: 'gpt-realtime-translate') and consume typed source/output transcript and audio events. Translation runs continuously from raw 24 kHz PCM16 mono input; configure language, source transcription and noise reduction with RealtimeTranslationSessionUpdateRequest. Request closeSession() and keep reading through RealtimeTranslationSessionClosedEvent before local cleanup.
Create scoped credentials with client.realtimeSessions.translations.createClientSecret(...). Native/server WebSockets can use them; browsers use WebRTC or an authenticated backend proxy because browser WebSockets cannot set authentication headers. Your application owns audio capture and playback.
Which audio models need migration?
The announced audio shutdowns require choosing the replacement workflow as well as a model:
| Shutdown | Existing family or endpoint | Replacement |
|---|---|---|
| January 6, 2027 | tts-1, tts-1-hd, gpt-4o-mini-tts |
Realtime speech generation with gpt-realtime-2.1-mini |
| January 20, 2027 | Legacy Realtime and audio families | gpt-realtime-2.1 / gpt-realtime-2.1-mini, or Chat audio with gpt-audio-1.5 |
| February 26, 2027 | Legacy Whisper/transcribe families; /audio/translations |
gpt-transcribe / gpt-live-transcribe, or Realtime translation |
See the official deprecation schedule for affected snapshots and route-specific migration guidance. Realtime beta was already removed on May 12, 2026; its retained codecs are for compatibility, and new sessions use GA. Model identifiers remain open strings.
How do I recover Live and Realtime WebSockets?
Enable LiveReconnectOptions or RealtimeReconnectOptions explicitly. Both default to rejecting sends during recovery; set maxQueueBytes to retain new, never-attempted frames. After reconnecting, restore application state and call connection.flushPending(), or retrieve frames with connection.takePending().
Live primary and fork connections require a fresh explicit start(...) acknowledgment before pending work can flush. Realtime and Translation configuration, history, and audio are never restored automatically. Finalize only while the session is connected. Attempted writes are never replayed; inspect connection.recovery!.done for the final unsent report.
Browser WebSockets reject custom headers. Use WebRTC or an authenticated backend proxy.
How do I signal Live sessions and control calls?
Use client.live for WebRTC/SIP signaling, explicit call controls, and recordings. The full example also handles verified incoming-call notices.
How do I use primary and sideband Live WebSockets?
Connect primary or sideband Live WebSockets to observe typed events and control a session. Your application handles media and tool delegation, and awaits graceful finalization.
How do I connect Live to Decisions?
Configure LiveDecisionsDelegationParam for native delegation, or add input/output transcript triggers with LiveDecisionTriggerInputParam. Live question groups allow up to 64 questions; use LiveDecisionQuestion for their distinct content rules.
Append shared context with LiveDecisionItemCreateParam, evaluate explicitly with a unique LiveDecisionCreateParam.eventId, and read LiveDecisionEvent.typedDecision. Wait for configuration/item acknowledgments before using new state. Trigger results identify their source transcript delta and can arrive out of order; your application decides which result to apply and performs any actions. When filtering WebRTC events, allow decision.event and each configured source transcript event.
How do I play Live audio fixtures and send SIP DTMF?
Send LiveOutputAudioFixturePlayParam.fromBytes(...) with up to 30 seconds of raw mono PCM16 little-endian audio at 24 kHz. Wait for LiveOutputAudioFixturePlaying (accepted), then LiveOutputAudioFixturePlayed (server mixer drained); transport audio may still be buffered. Input is dropped and instruction/thinking/commentary appends are rejected during playback. Independent input mute remains separate.
For SIP calls, send one key with LiveTransportDTMFSendParam(event: '#', eventId: ...) on the server sideband. LiveTransportDTMFSent confirms sending to the SIP trunk; LiveTransportDTMFReceived carries caller keypresses. Match optional client correlation IDs and handle server errors explicitly.
How do I fork stored Live sessions and group captions?
Fork a stored Live session and use transcript helpers to group captions. The example covers inherited state and caller-owned channel cleanup.
Agents and Vaults #
How do I save and update an agent configuration?
Use client.agents to save reusable model, instruction, and tool configuration. Creating an agent stores configuration without starting a session; updates preserve omitted fields, while clearX flags reset nullable settings.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
final agent = await client.agents.create(
CreateAgentRequest(model: 'gpt-5.5', name: 'Research assistant'),
);
try {
final updated = await client.agents.update(
agent.id,
UpdateAgentRequest(name: 'Updated research assistant'),
);
print(updated.name);
} finally {
await client.agents.delete(agent.id);
}
} finally {
client.close();
}
}
Durable agent sessions
Use client.agents.sessions to create sessions, observe events, and submit function results or cancellation. Cancelling a local event subscription stops observation only; cancel durable work explicitly through session inputs.
For reconnecting observers, subscribe with events.stream(..., onReady: ...), buffer updates, restore current session/history by item ID, then resume live handling. There is no replay cursor. Refresh requiredActions before an explicit browser decision; authentication values use only dedicated typed inputs with automatic retries disabled. An empty HTTP 202 confirms acceptance, so continue observing current state.
→ Offline browser actions and current-state recovery examples
How do I configure Agent context and action review?
Use AgentCompactionConfig(async: false) for blocking compaction and AgentExperimentalConfig(timeAwareness: true) for periodic current-time reminders. Compaction updates replace the configuration; null or {} restores background compaction. Experimental updates merge supplied keys, preserving omitted values. Request AgentServiceTierParam.ultrafast with a supported model when appropriate.
Set session review to SessionReviewParam.autoReview to review eligible actions automatically, or .none for existing execution behavior. Updates apply to new root turns; existing turns and their subagents keep their mode. Action review is independent of spending limits. Replace session tools through AgentSessionAgentUpdate; omission keeps them, while null or [] clears them. Function/MCP changes apply on the next model call, and built-in changes by the next turn.
Filter session lists with metadata: {'project': 'demo'}; all pairs must match, and updates may take time to appear in filtered results. Keep the same filters when advancing a cursor.
How do I schedule work with Agent automations?
Use client.agents.automations for one-time or cron schedules targeting a new session or an existing conversation. Creating, updating, pausing, and resuming a schedule do not invoke it immediately; call .invocations.create(automationId) explicitly for a manual delivery, including while paused.
Inspect .invocations.list or .retrieve for delivery status and the session ID. A completed delivery means the session accepted the input; follow session events for the Agent's result. Pausing or deleting a schedule leaves accepted session work running. Enable AgentTool.automations() or AgentSessionTool.automations() to let an Agent schedule follow-ups itself.
Follow one turn on an idle Agent session
Use this lazy helper with one application input writer. It retrieves idle state, subscribes before input, then observes the selected root turn through its terminal event and session idle. Raw sessions.events remains available for active-session steering and manual actions.
final run = client.agents.sessions.stream(
sessionId,
input: AgentSessionInitialInput.text('Continue the task.'),
);
try {
await for (final event in run.events) {
print(event.type);
}
} finally {
await run.close();
}
For sequential pulls that pause and continue, use run.nextEvent() instead of the Stream adapter. Stream break/close/abort stops only local observation; backend cancellation is a separate explicit raw input. Progress queues have bounded count/byte retention and fail on overflow.
Handle local functions during an Agent turn
Keep canonical tool definitions in the saved Agent or creation request, then opt into local implementations separately. The original call event arrives before its handler runs; advancing the same cursor executes registered calls sequentially.
final run = client.agents.sessions.stream(
sessionId,
input: AgentSessionInitialInput.text('Double 2.'),
toolHandlers: {
'double_number': (args) => {'answer': (args['number']! as int) * 2},
},
);
try {
await for (final event in run.events) {
// Render progress; unknown functions stay manual.
}
} finally {
await run.close();
}
Use sessions.createRun(request, toolHandlers: ...) for lazy streamed creation;
explicit stream: false rejects locally. Callbacks stay out of wire JSON. Calls
are deduplicated for the entire run, with a configurable 1,024-call budget that
fails on overflow. Arguments must be JSON objects; failures send only
Tool handler failed.. Optional onToolError receives private local details.
Closing or aborting stops further submission; application side effects already
performed are not undone. No executor, browser authentication or sandbox is added.
→ Offline local-tools example, with --create for creation
Collect or validate a completed Agent answer
finalResult() on a fresh run drains the same observation and returns completed
root-turn messages. To render some progress first, enable collection before
consumption and use the controlled cursor:
final run = client.agents.sessions.stream(
sessionId,
input: AgentSessionInitialInput.text('Summarize the task.'),
).withResultCollection();
try {
final firstEvent = await run.nextEvent();
final result = await run.finalResult();
print(result.outputText);
} on AgentSessionRunResultException catch (error) {
// Inspect error.reason, partial turn/messages/actions and cause explicitly.
} finally {
await run.close();
}
Collection defaults to 1,024 final messages and 4 MiB of retained snapshots;
overflow fails explicitly. Default progress retains no collector history. A
Stream break closes observation; nextEvent() supports partial continuation.
Failed/cancelled turns, unresolved actions and incomplete observation return
private typed errors. After a manual action, available canonical clearing events
can be drained; HTTP 202 alone does not prove the action finished.
Use run.withOutput(AgentSessionOutputBinding(format: ..., parse: ...)) before
starting for typed output. Supply an Agents JSON schema and a synchronous local
validator. Creation binds agent.text.format; follow-ups change no session
configuration. Every completed text block must validate, and a parse failure
preserves the successful raw result. Parsed application values remain owned by
the parser. Result Futures cache success and failure without replaying work.
→ Offline raw/typed result example, including creation and parse failure
Session history and traces
Read session items, turns, and published OTLP traces through client.agents.sessions. Trace reads require organization export settings and permissions; a page contains only traces published when it is read.
Agent session subagents
Inspect child state and item/turn history through client.agents.sessions.subagents. These read-only methods do not create, resume, or interrupt child agents.
Agent environments and templates
Use client.agents.environments and .templates to save hosted setup and prewarm eligible environments. Environment and session lifetimes are independent; deleting a template does not stop a session. Eligible hosted sandboxes include the Artifact SDK and document skills inside the environment; prewarming uses the existing environment creation flow.
How do I upload Agent inputs and download result files?
Use AgentFiles(client).prepare(selected) to upload explicit bytes or streams with purpose=user_data, then pass prepared.files to AgentSessionEnvironment.openaiHosted(files: ...). Use .stage(environmentId, selectedFile) to copy one upload into an existing connected environment.
Bind downloads to a completed run result and an explicit binary sink:
final result = await run.withResultCollection().finalResult();
final artifacts = AgentResultArtifacts(client: client, result: result);
await artifacts.downloadTo(
'/workspace/outputs/report.pdf',
sink: (bytes) => outputSink.add(bytes),
);
The helper finds one exact session/turn/path match across every page. Callers own sink flush/close and upload cleanup; a failed preparation exposes observed IDs in AgentFilePreparationException.prepared. Streams are materialized one file at a time within a configurable local budget (64 MiB by default).
For explicit local files, import package:openai_dart/openai_dart_agent_files_io.dart. AgentFileSystem accepts paths beneath a stable application-owned directory and creates new output files only; it rejects overwrites and symlinks. Metadata checks cannot prove identity against same-metadata replacement, so this adapter requires stable directories.
→ Offline portable upload/result/download example · Optional local-file example
Agent environment files and published artifacts
Use client.agents.environments.files for live workspace files and client.agents.sessions.artifacts for published outputs. Download artifacts to retain them before deleting a session; use downloadStream for incremental bytes.
Vaults and write-only credentials
Use client.vaults and .credentials to store or rotate OAuth, bearer, and hosted environment secrets. Credentials are write-only; deleting a stored credential does not revoke its provider token or cancel running work.
Organization administration #
How do I use Admin keys, storage, and Decisions usage?
Use a separate OpenAIAdminClient. fromEnvironment() reads OPENAI_ADMIN_KEY; project client credentials and defaults are never inherited. Admin credentials are used only by this bounded administration namespace. Custom providers supply a Bearer Authorization header; configure organization/routing headers explicitly in OpenAIAdminConfig.
final admin = OpenAIAdminClient.fromEnvironment();
try {
final usage = await admin.organization.usage.decisions(
startTime: 1793404800,
groupBy: [DecisionsUsageGroupBy.model, DecisionsUsageGroupBy.apiSource],
);
// Pass usage.nextPage as page explicitly when usage.hasMore is true.
print(usage.data.length);
} finally {
admin.close();
}
The 12 supported operations cover AWS/Azure/GCP external keys, AWS/Azure/GCP/OCI external storage, project API-key scope/relative-expiry updates, and Decisions usage. Empty key scopes means All permissions within the owner's effective access; eligible HTTP retries reapply relative expiry. Storage status and deletion effects remain service-owned. Historical Admin APIs are outside this slice. Redirects are disabled; automatic diagnostics redact key/provider metadata, IDs, and usage filters.
See the offline Admin example for synthetic key validation, OCI storage, service-account-owned key updates, and 30-minute cache-write usage. It uses only MockClient, with no real key registration, cloud access, or billing queries. The narrower import package:openai_dart/openai_dart_admin.dart is also available.
Legacy and retiring APIs #
What remains of the Videos API?
The Videos API and Sora 2 shut down on September 24, 2026. Retained types and this example are historical compatibility references. See the official deprecation schedule.
What is the Evals retirement timeline?
Evals became read-only on October 31 and is scheduled to shut down on November 30, 2026. Plan a migration using the official retirement guidance. The retained example documents the historical API.
Error Handling #
Handle API errors and retries
Catch typed exceptions such as RateLimitException, or ApiException for HTTP failures. OpenAIException also covers client and transport failures.
import 'package:openai_dart/openai_dart.dart';
Future<void> main() async {
final client = OpenAIClient.fromEnvironment();
try {
await client.responses.create(
const CreateResponseRequest(
model: 'gpt-5.5',
input: ResponseInput.text('Hello!'),
),
);
} on RateLimitException catch (error) {
print('Rate limit: ${error.message}; retry hint: ${error.retryAfter}');
} on ApiException catch (error) {
print('HTTP ${error.statusCode}: ${error.message}');
} on OpenAIException catch (error) {
print('Client error: ${error.message}');
} finally {
client.close();
}
}
Cloneable requests retry transient 429 responses; 5xx, timeout, and connection retries require an idempotent method. Billing/quota errors require action, and POST 5xx, multipart requests, and streams are not automatically replayed. Server retry hints are exposed as retryAfter; maxRetries: 0 disables automatic retries.
Examples #
Complete runnable workflows are in example/. Examples marked offline use local or mock transports; other examples can make paid API calls. Start with responses_example.dart.
Responses, Chat, Decisions, and embeddings
| Example | Description |
|---|---|
| vertex_responses_example.dart | Offline. injected Google tokens, exact Vertex root and all six Responses lifecycle paths |
| runtime_config_example.dart | Offline. configuration snapshots, refreshed handles and request-local credential rotation |
| responses_example.dart | Responses API with built-in tools |
| openai_dart_example.dart | Quick-start overview |
| web_search_example.dart | Web search with Responses API |
| input_tokens_example.dart | Input token counting |
| conversations_example.dart | Conversations API for state management |
| chat_example.dart | Chat completions, multi-turn conversations, and legacy cache retention |
| streaming_example.dart | Content streaming, detailed final usage, and obfuscation controls |
| tool_calling_example.dart | Function calling with tool definitions |
| vision_example.dart | Image analysis with vision models |
| decisions_example.dart | Typed Decisions questions, refusals, usage, and inline images |
| decisions_ga_example.dart | Offline JSON evidence, tool history, multimodal questions, and shared-input caching |
| decision_image_urls_example.dart | Offline. HTTP(S)/data image references, exact mixed input and one mock POST |
| embeddings_example.dart | Text embeddings with dimension control |
Images, audio, video, and live sessions
| Example | Description |
|---|---|
| images_example.dart | GPT Image generation |
| image_model_selection_example.dart | Local generation/multipart/JSON-edit model contracts without API calls |
| image_markup_example.dart | Offline. PNG/reference overlays, safety identifiers and completed edit events |
| audio_example.dart | Text-to-speech and transcription |
| speech_streaming_example.dart | Offline. buffered/byte/SSE speech, voice references and usage |
| existing_audio_example.dart | Offline. modern file fields, verbose/raw translation, open/custom Chat voices and AAC |
| chat_audio_example.dart | Chat audio output, ID-only replay, and partial stream accumulation |
| videos_example.dart | Historical Videos API reference; endpoint retired |
| realtime_example.dart | Realtime API (WebSocket and WebRTC) |
| realtime_input_example.dart | Offline. acknowledged history references, typed new input and out-of-band response output |
| realtime_translation_example.dart | Offline. scoped translation secret, noise strength, typed audio/transcripts and flush/close |
| live_http_example.dart | Offline. WebRTC/SIP signaling, explicit call controls, verified incoming notice, WAV downloads and REST fork |
| live_media_example.dart | Offline. raw audio fixture acceptance/drain, independent mute, and SIP DTMF directions |
| live_websocket_example.dart | Offline. primary/sideband Live, concurrent event taps, manual delegation and graceful finalization |
| live_decisions_example.dart | Offline. native Decisions delegation, shared items, and a correlated transcript trigger |
| live_workflows_example.dart | Offline. stored forks, inherited state, compact Responses, caption grouping and borrowed-channel cleanup |
| voice_consents_example.dart | Offline. upload/list/retrieve/rename/delete consent lifecycle and explicit pagination |
| voices_example.dart | Offline. explicit consent and sample upload, then caller-selected custom voice reference |
| prompt_voices_example.dart | Offline. create a prompt voice, select it for Live, and explicitly delete it |
Files, batches, errors, webhooks, and safety
| Example | Description |
|---|---|
| files_example.dart | File upload and management |
| uploads_example.dart | Large file multipart uploads |
| batches_example.dart | Batch processing for async jobs |
| fine_tuning_example.dart | Fine-tuning job management |
| evals_example.dart | Historical Evals reference; read-only until November 30, 2026 |
| models_example.dart | Model listing and retrieval |
| moderation_example.dart | Content moderation |
| content_provenance_checks_example.dart | Content provenance (C2PA/SynthID) detection |
| error_handling_example.dart | Exception handling patterns |
| retry_guidance_example.dart | Local transient, permanent-quota, and long-hint scenarios without API calls |
| agent_environment_webhooks_example.dart | Offline. environment subscriptions, signed notifications, repeated-ID handling and safe retrieval |
| webhooks_example.dart | Offline. signed receiver, acknowledgment and caller-owned deduplication |
| webhook_endpoints_example.dart | Offline. project endpoint lifecycle, pagination, discovery, rotation and test status |
| safety_example.dart | Offline. verified notifications and separately scoped alert/case retrieval |
| safety_explanations_example.dart | Offline. project alert explanation presence, copy/clear and private diagnostics |
| monitoring_errors_example.dart | Offline. typed HTTP/SSE monitoring failures and explicit scoped investigation |
Advanced Responses workflows
| Example | Description |
|---|---|
| responses_websocket_example.dart | Offline. low-level warmup, two persistent lanes and incremental continuation |
| responses_websocket_session_example.dart | Offline. bounded sessions, manual tool continuation, fork barrier and compact replay |
| responses_steering_example.dart | Offline. steer a running Responses request |
| responses_recovery_example.dart | Offline. recover a Responses WebSocket |
| websocket_recovery_example.dart | Local peer. reconcile a Realtime session before flushing pending work |
| async_tools_example.dart | Local async function/custom jobs, original call IDs and latest-response continuation |
| tool_search_example.dart | Offline. client tool-search continuation with the original call ID and complete discovered definitions |
| web_search_controls_example.dart | Local GA filters, image results, sources, and REST/SSE parsing without API calls |
| reasoning_replay_example.dart | Offline. typed reasoning and function history replay with opaque state and original ordering |
| configuration_updates_example.dart | Offline. change reasoning effort during a conversation |
| prompt_cache_example.dart | Responses prewarming, comparison diagnostics, and narrow Chat cache options |
| responses_cache_usage_example.dart | Offline 30m/12h cache boundaries and separate hosted-tool usage |
| containers_example.dart | Container memory/network configuration, Code Interpreter IDs, and files |
| shell_tools_example.dart | Offline. hosted configuration, synthetic local continuation, and typed shell stream events |
| compaction_progress_example.dart | Offline. nonterminal compaction progress and opaque final output preservation |
| access_programs_example.dart | Offline. access-program selection, server defaults and effective returned metadata |
| responses_injection_example.dart | Offline. inject multi-agent tool results |
Agents, Vaults, and other resources
| Example | Description |
|---|---|
| saved_agents_example.dart | Offline. saved-agent CRUD, tool configuration, pagination, replacement and clear/reset |
| agent_settings_example.dart | Offline. compaction, time awareness, session review/tools, ultrafast and exact metadata filters |
| agent_automations_example.dart | Offline. once/cron schedules, new/existing session targets, pause/resume, explicit invocation and delivery history |
| agent_sessions_example.dart | Offline. durable sessions, persistent observation, manual function result and explicit cancellation |
| agent_browser_actions_example.dart | Offline. explicit origin decisions, private authentication and observed acceptance |
| agent_session_recovery_example.dart | Offline. subscribe/buffer, current-state/history reconciliation and local observer cleanup |
| agent_session_run_example.dart | Offline. lazy idle follow-up, selected root boundary, controlled pulls and separate cancellation |
| agent_local_tools_example.dart | Offline. opt-in sequential function dispatch for streamed creation or idle follow-up |
| agent_session_result_example.dart | Offline. raw/typed completed results, partial cursor continuation and local parse failure |
| agent_session_history_example.dart | Offline. root/turn history and published OTLP trace pagination |
| agent_subagents_example.dart | Offline. Agent session subagents |
| agent_environments_example.dart | Offline. template CRUD and owned hosted environment prewarming, pagination and safe inspection |
| agent_file_helpers_example.dart | Offline. selected bytes, explicit staging, completed run identity and binary artifact sink |
| agent_files_io_example.dart | Local only. explicit regular-file selection beneath an application-owned directory; no API calls |
| agent_files_artifacts_example.dart | Offline. Agent environment files and published artifacts |
| admin_example.dart | Offline. isolated Admin credentials, external keys, OCI storage, key updates, and Decisions usage |
| vaults_example.dart | Offline. Vault CRUD and write-only credential create/rotate with safe inspection |
| chatkit_example.dart | ChatKit sessions and threads |
| skills_example.dart | Skills management |
| assistants_example.dart | Historical Assistants reference; endpoint retired |
| completions_example.dart | Legacy completions API |
API Coverage #
Supported APIs and remaining gaps
| API | Support |
|---|---|
| Responses | HTTP and SSE, persistent WebSockets, bounded lane sessions, steering, opt-in connection recovery, and beta tool-result injection |
| Chat Completions | Generation and streaming; stored-completion management pending |
| Decisions | Predicate, choice, and score questions |
| Embeddings | Text vectors with dimension control |
| Images | Generation, editing, and streaming |
| Audio | Speech, transcription, translation, voice consents, prompt/sample voice creation, and saved voice deletion; consent phrase lookup remains untyped |
| Videos | Retained compatibility types; API shut down September 24, 2026 |
| Realtime | WebSocket and WebRTC sessions, typed response input references, noise strength, Translation sockets, and opt-in recovery with explicit pending delivery |
| Live | HTTP call controls, recordings, WebSockets, native Decisions delegation/triggers, audio fixtures, SIP DTMF, forks, transcript helpers, and opt-in recovery with fresh startup gating |
| Files and Uploads | File management and large multipart uploads |
| Batches | Asynchronous batch processing |
| Models | Listing and retrieval |
| Moderations | Text and image moderation |
| Fine-tuning | Job management; some grader/checkpoint operations pending |
| Evals | Read-only since October 31; scheduled shutdown November 30, 2026 |
| Conversations | Conversation and item management |
| Containers | Memory, network policy, skills, and files |
| Content Provenance Checks | C2PA and SynthID inspection |
| Webhooks | Local signed verification and project endpoint management |
| Safety | Read-only project alerts, organization cases, and typed monitoring details |
| Agents | Saved agents, context settings, action review, durable sessions, scheduled automations and invocations, metadata filters, root/child history, hosted environments, portable file preparation, explicit staging, and completed-result artifacts |
| Vaults | Vault management and write-only credentials |
| Organization Admin | Separate Admin credentials; external keys/storage, project API-key updates, and Decisions usage (12 operations) |
| ChatKit Beta and Skills | Sessions/threads and skills management |
| Assistants, Threads, Messages, and Runs | Historical types; Assistants API retired; separate import |
| Vector Stores | File search storage and ingestion; separate Assistants import |
| Completions | Legacy compatibility API; prefer Responses |
Some Responses tool/configuration details and historical administration APIs remain outside current coverage. See the completed October alignment and remaining limits for the detailed scope.
Official Documentation #
Sponsor #
If these packages are useful to you or your company, please consider sponsoring the project. Your support helps maintain the packages and fund API integration tests for the Dart and Flutter community.
License #
This package is licensed under the MIT License.
This is a community-maintained package and is not affiliated with or endorsed by OpenAI.