-
-
Notifications
You must be signed in to change notification settings - Fork 541
Contracts Project: Introduction and Upgrade Guide
Tolga Kayhan edited this page Nov 2, 2025
·
1 revision
This document introduces the new Betalgo.Ranul.OpenAI.Contracts project, explains why we’re adopting it, outlines what changed, and shows how to upgrade your code.
-
New project:
Betalgo.Ranul.OpenAI.Contractscentralizes request/response models, enums/value types, and capability interfaces. - Direction: We’ll roll this pattern out gradually across the SDK as models and APIs grow in complexity.
- Roadmap: The next update targets GPT‑5 features and the Reasoning API.
- Stability: These changes will be tested for a while and may evolve; we’ve kept them minimal to reduce friction.
- Complex model structures and API variants demand stronger, decoupled contracts.
- Centralized contracts give us clearer versioning, reusability, and easier migrations.
- Added
Betalgo.Ranul.OpenAI.Contractswith:- Requests:
Requests.Image.CreateImageRequest,CreateImageEditRequest,CreateImageVariationRequest - Responses:
Responses.Image.ImageResponse, shared base:Responses.Base.ResponseBase,ResponseBaseHeaderValues,ResponseError,RateLimitInfo,OpenAIInfo - Enums/value types:
Enums.*andEnums.Image.*(e.g.,ImageSize,ImageOutputFormat,ImageResponseFormat,ImageModeration,Voice, roles) - Types:
Types.FormFile,Types.FormFileOrList,Types.StringOrList - Interfaces:
Interfaces.IHasImageSize,IHasImageBackground,IHasImageOutputFormat,IHasImageQuality,IHasModelImage
- Requests:
- Removed legacy image request models from
OpenAI.SDK/ObjectModels/RequestModelsand replaced with Contracts requests. - Introduced V2 HTTP helpers wired to
ResponseBase; legacy helpers retained for backward compatibility. - Request/response models are now classes instead of records; usage stays the same (object initializers and JSON names unchanged).
- Added:
Betalgo.Ranul.OpenAI.Contracts/** - Removed:
OpenAI.SDK/ObjectModels/RequestModels/ImageCreateRequest.cs,ImageEditCreateRequest.cs,ImageVariationCreateRequest.cs,SharedImageRequestBaseModel.cs - Updated:
OpenAI.SDK/Interfaces/IImageService.cs,OpenAI.SDK/Managers/OpenAIImage.cs, Playground image tests - Added (compat):
OpenAI.SDK/Extensions/HttpclientExtensionsLegacy.cs
| Old type/namespace | New type/namespace |
|---|---|
OpenAI.SDK.ObjectModels.RequestModels.ImageCreateRequest |
Betalgo.Ranul.OpenAI.Contracts.Requests.Image.CreateImageRequest |
OpenAI.SDK.ObjectModels.RequestModels.ImageEditCreateRequest |
Betalgo.Ranul.OpenAI.Contracts.Requests.Image.CreateImageEditRequest |
OpenAI.SDK.ObjectModels.RequestModels.ImageVariationCreateRequest |
Betalgo.Ranul.OpenAI.Contracts.Requests.Image.CreateImageVariationRequest |
OpenAI.SDK.ObjectModels.SharedModels.SharedImageRequestBaseModel |
Replaced by small capability interfaces under Betalgo.Ranul.OpenAI.Contracts.Interfaces
|
Enums.VoiceEnum |
Betalgo.Ranul.OpenAI.Contracts.Enums.Voice (value type) |
Enums.MessageRole |
Betalgo.Ranul.OpenAI.Contracts.Enums.ChatCompletionRole and/or AssistantMessageRole
|
Top-level Enums.Image*
|
Betalgo.Ranul.OpenAI.Contracts.Enums.Image.* (moved/clarified) |
Responses.Base.ResponseHeaderValues |
Betalgo.Ranul.OpenAI.Contracts.Responses.Base.ResponseBaseHeaderValues |
Additional API change:
-
IImageServicemethodsCreateImageEditandCreateImageVariationnow returnImageResponse(previously returnedImageCreateResponse).
IImageService now consumes Contracts models and returns Contracts ImageResponse for all image operations:
Task<ImageResponse> CreateImage(CreateImageRequest imageCreate, CancellationToken cancellationToken = default);
Task<ImageResponse> CreateImageEdit(CreateImageEditRequest imageEditCreateRequest, CancellationToken cancellationToken = default);
Task<ImageResponse> CreateImageVariation(CreateImageVariationRequest imageEditCreateRequest, CancellationToken cancellationToken = default);Notes:
- All three methods return
Contracts.Responses.Image.ImageResponse, unifying image responses on the Contracts model.
- Update usings/namespaces
- Remove:
using OpenAI.SDK.ObjectModels.RequestModels; - Add:
using Betalgo.Ranul.OpenAI.Contracts.Requests.Image;using Betalgo.Ranul.OpenAI.Contracts.Enums.Image;- Optionally:
using Betalgo.Ranul.OpenAI.Contracts.Types; - For roles/voices:
using Betalgo.Ranul.OpenAI.Contracts.Enums;
- Switch to Contracts request models
- Image create:
var imageResult = await sdk.Image.CreateImage(new()
{
Prompt = "Laser cat eyes",
N = 1,
Size = ImageSize.Size256
});- Image edit (supports single or multiple images via
FormFileOrList):
var imageResult = await sdk.Image.CreateImageEdit(new()
{
Image = new FormFile(originalFileName, originalFile), // or: new List<FormFile> { ... }
Mask = new(maskFileName, maskFile),
Prompt = "A sunlit indoor lounge area with a pool containing a cat",
N = 4,
Size = ImageSize.Size1024,
ResponseFormat = ImageResponseFormat.Url,
User = "TestUser"
});- Image variation:
var imageResult = await sdk.Image.CreateImageVariation(new()
{
Image = new(originalFileName, originalFile),
N = 2,
Size = ImageSize.Size256,
ResponseFormat = ImageResponseFormat.Url,
User = "TestUser"
});- Use the new file/union types where needed
public class FormFile(string name, Stream data)
{
public string Name { get; set; } = name;
public Stream Data { get; set; } = data;
}
// Single or list with implicit conversions
FormFileOrList single = new FormFile("cat.png", stream);
FormFileOrList many = new List<FormFile> { new("a.png", a), new("b.png", b) };- Update enums/value types
- Roles:
var role = ChatCompletionRole.Assistant; // developer, system, user, assistant, tool- Voices:
var voice = Voice.Alloy; // echo, fable, nova, onyx, shimmer- Image response/output formats and size:
var format = ImageOutputFormat.Png; // jpeg, webp
var responseFormat = ImageResponseFormat.Url; // or: ImageResponseFormat.Base64
var size = ImageSize.Size1024; // 256, 512, 1024, 1792x1024, 1024x1792We replaced many traditional C# enums with small, immutable value types (e.g., ImageResponseFormat, ImageOutputFormat, ImageSize, Voice, ChatCompletionRole). These types are designed to be both type‑safe and future‑proof:
-
IDE IntelliSense: Known values are exposed as
staticproperties, so your IDE will autocomplete them (as shown in the screenshot). This makes code self‑documenting and prevents typos. -
Future‑proofing: These types support implicit conversion to/from
string. If OpenAI adds a new value we haven’t shipped yet, you can still use it immediately by assigning a raw string. No waiting for a library update. -
JSON friendly: Each type includes a
JsonConverterso it serializes/deserializes as a simple string in requests/responses. - Case‑insensitive equality: Comparisons are insensitive to letter case, making checks straightforward.
Examples

This approach gives you the best of both worlds: discoverability and safety via IntelliSense for known values, plus immediate access to new values as plain strings without breaking changes.
- Response handling and headers
- All image endpoints return
ImageResponse, which implementsIDefaultResult<string>andIDefaultResults<string>:
var first = imageResponse.Result; // first URL or base64
var all = imageResponse.Results; // all URLs/base64 strings- Headers via
ResponseBaseHeaderValues:
var headers = imageResponse.HeaderValues;
var requestId = headers?.XRequestId;-
ImageModerationvalue type (low,auto) for gpt-image-1 moderation. -
StringOrListandFormFileOrListunions with converters for flexible JSON shape. -
ResponseBasenow exposesHttpStatusCode,HeaderValues,Error, andIsDeltahelpers.
- Legacy HTTP helpers (
OpenAI.SDK/Extensions/HttpclientExtensionsLegacy.cs) remain for existing flows. - Image enums were reorganized but preserve literal values; mostly namespace changes plus clarified names.
- Image create/edit/variation now share the same
ImageResponsereturn type.
- This is the first pass; Contracts usage will expand across the SDK.
- Upcoming: GPT‑5 features, Reasoning API alignment, and unifying image edit/variation responses on Contracts base types.
- Expect minor adjustments during testing; we’ll keep migrations straightforward.