softcreatr/php-openai-sdk

A powerful and easy-to-use PHP SDK for the OpenAI API, allowing seamless integration of advanced AI-powered features into your PHP projects.

Maintainers

Package info

github.com/SoftCreatR/php-openai-sdk

pkg:composer/softcreatr/php-openai-sdk

Transparency log

Statistics

Installs: 1 047

Dependents: 0

Suggesters: 0

Stars: 12

Open Issues: 0

4.0.2 2026-07-14 08:23 UTC

This package is auto-updated.

Last update: 2026-07-14 08:24:17 UTC


README

Tests Latest Release PHP License

A lightweight, underrated PSR-17/PSR-18 client for the current OpenAI API, with examples for every exposed SDK method, SSE streaming, streamed multipart uploads, structured errors, project scoping, and webhook signature verification.

Requirements

  • PHP 8.1 or newer. CI tests PHP 8.1, 8.2, 8.3, 8.4, and 8.5.
  • A PSR-17 request, stream, and URI factory.
  • A PSR-18 HTTP client.
  • The JSON extension.

Guzzle is used below because it provides both the PSR-17 factories and PSR-18 client implementation. The SDK itself depends only on the PSR interfaces, so other compliant implementations remain supported.

Installation

composer require softcreatr/php-openai-sdk guzzlehttp/guzzle

Client Setup

<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use SoftCreatR\OpenAI\OpenAI;

$factory = new HttpFactory();
$openAI = new OpenAI(
    requestFactory: $factory,
    streamFactory: $factory,
    uriFactory: $factory,
    httpClient: new Client(['stream' => true]),
    apiKey: (string) getenv('OPENAI_API_KEY'),
    organization: (string) getenv('OPENAI_ORGANIZATION_ID'),
    project: (string) getenv('OPENAI_PROJECT_ID'),
);

Keep API keys on the server and out of source control. Organization and project IDs are optional.

Responses API

The Responses API is the recommended interface for new text and agentic integrations.

use const JSON_THROW_ON_ERROR;

$response = $openAI->createResponse([
    'model' => 'gpt-5.4-mini',
    'input' => 'Give me a one-sentence summary of PSR-18.',
]);

$result = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR);
echo $result['output'][0]['content'][0]['text'];

Endpoint methods return a PSR-7 ResponseInterface. Streaming calls return null after delivering their events to the callback.

Arguments

Body-only endpoints use a single body array:

$openAI->createEmbedding([
    'model' => 'text-embedding-3-small',
    'input' => 'A sentence to embed.',
]);

For endpoints with path parameters, a single combined array is the preferred v4 form. Path fields are separated from the request body using the endpoint template:

$openAI->updateConversation([
    'conversation_id' => 'conv_abc123',
    'metadata' => ['customer' => 'acme'],
]);

The v3 two-array form remains supported for existing integrations:

$openAI->updateConversation(
    ['conversation_id' => 'conv_abc123'],
    ['metadata' => ['customer' => 'acme']],
);

For GET and DELETE methods, non-path values become RFC 3986 query parameters. Path parameter values are URL encoded. The explicit form is available when method names are determined at runtime:

$response = $openAI->request(
    'listFiles',
    ['limit' => 20, 'after' => 'file_abc123'],
    customHeaders: ['X-Trace-Id' => 'trace_abc123'],
);

Streaming

Set stream to true and pass a callback. The decoder supports arbitrarily split chunks, CRLF and LF delimiters, comments, multiline data fields, final unterminated frames, and [DONE].

$openAI->createResponse(
    [
        'model' => 'gpt-5.4-mini',
        'input' => 'Write a short haiku about PHP.',
        'stream' => true,
    ],
    static function (array $event): void {
        if ($event['type'] === 'response.output_text.delta') {
            echo $event['delta'];
        }
    },
);

An ordinary JSON response is still returned when a callback is supplied without requesting an SSE stream.

File Uploads

Multipart endpoints accept readable local file paths. Files are copied as raw bytes into a temporary stream rather than being base64 encoded or assembled in one large PHP string.

$response = $openAI->uploadFile([
    'file' => __DIR__ . '/data.jsonl',
    'purpose' => 'user_data',
]);

Repeated upload fields such as image inputs and skill files accept arrays of paths. Nested non-file values are encoded using bracket notation.

Errors

4xx and 5xx responses throw OpenAIException. The exception keeps the parsed API error, raw response body, response headers, status code, and x-request-id for diagnostics.

use SoftCreatR\OpenAI\Exception\OpenAIException;

try {
    $openAI->retrieveModel(['model' => 'missing-model']);
} catch (OpenAIException $exception) {
    error_log(sprintf(
        'OpenAI request %s failed (%d): %s',
        $exception->getRequestId() ?? 'unknown',
        $exception->getCode(),
        $exception->getMessage(),
    ));
}

PSR-18 transport failures are wrapped in OpenAIException and retain the original exception as getPrevious().

Webhooks

Verify the signature against the exact raw request body before decoding or changing it. The verifier follows OpenAI's webhook guide and supports multiple v1 signatures during secret rotation.

use SoftCreatR\OpenAI\Webhook\WebhookVerifier;

$rawBody = (string) $request->getBody();
$event = (new WebhookVerifier((string) getenv('OPENAI_WEBHOOK_SECRET')))
    ->unwrap($rawBody, $request->getHeaders());

if ($event['type'] === 'response.completed') {
    // Handle the completed response idempotently.
}

The default replay tolerance is 300 seconds. Invalid signatures throw InvalidWebhookSignatureException; valid signatures with invalid JSON throw WebhookException.

Examples

Examples load the ignored project-level .env through examples/OpenAIFactory.php:

cp .env.example .env
php examples/responses/createResponse.php

Set OPENAI_ADMIN_KEY only when running examples under examples/administration.

Supported Methods

The catalog follows the current OpenAI API reference. Fine-tuning is retained for transitional compatibility and is marked deprecated. APIs that OpenAI classifies as legacy or has scheduled for shutdown are intentionally absent.

Administration

SDK method HTTP route Request body Example
activateCertificates POST /organization/certificates/activate json PHP
activateProjectCertificates POST /organization/projects/{project_id}/certificates/activate json PHP
addGroupUser POST /organization/groups/{group_id}/users json PHP
addProjectGroup POST /organization/projects/{project_id}/groups json PHP
archiveProject POST /organization/projects/{project_id}/archive none PHP
assignGroupRole POST /organization/groups/{group_id}/roles json PHP
assignProjectGroupRole POST /projects/{project_id}/groups/{group_id}/roles json PHP
assignProjectUserRole POST /projects/{project_id}/users/{user_id}/roles json PHP
assignUserRole POST /organization/users/{user_id}/roles json PHP
createAdminApiKey POST /organization/admin_api_keys json PHP
createGroup POST /organization/groups json PHP
createInvite POST /organization/invites json PHP
createOrganizationRole POST /organization/roles json PHP
createOrganizationSpendAlert POST /organization/spend_alerts json PHP
createProject POST /organization/projects json PHP
createProjectRole POST /projects/{project_id}/roles json PHP
createProjectServiceAccount POST /organization/projects/{project_id}/service_accounts json PHP
createProjectSpendAlert POST /organization/projects/{project_id}/spend_alerts json PHP
createProjectUser POST /organization/projects/{project_id}/users json PHP
deactivateCertificates POST /organization/certificates/deactivate json PHP
deactivateProjectCertificates POST /organization/projects/{project_id}/certificates/deactivate json PHP
deleteAdminApiKey DELETE /organization/admin_api_keys/{key_id} none PHP
deleteCertificate DELETE /organization/certificates/{certificate_id} none PHP
deleteGroup DELETE /organization/groups/{group_id} none PHP
deleteInvite DELETE /organization/invites/{invite_id} none PHP
deleteOrganizationRole DELETE /organization/roles/{role_id} none PHP
deleteOrganizationSpendAlert DELETE /organization/spend_alerts/{alert_id} none PHP
deleteProjectApiKey DELETE /organization/projects/{project_id}/api_keys/{api_key_id} none PHP
deleteProjectModelPermissions DELETE /organization/projects/{project_id}/model_permissions none PHP
deleteProjectRole DELETE /projects/{project_id}/roles/{role_id} none PHP
deleteProjectServiceAccount DELETE /organization/projects/{project_id}/service_accounts/{service_account_id} none PHP
deleteProjectSpendAlert DELETE /organization/projects/{project_id}/spend_alerts/{alert_id} none PHP
deleteProjectUser DELETE /organization/projects/{project_id}/users/{user_id} none PHP
deleteUser DELETE /organization/users/{user_id} none PHP
getAudioSpeechesUsage GET /organization/usage/audio_speeches none PHP
getAudioTranscriptionsUsage GET /organization/usage/audio_transcriptions none PHP
getCertificate GET /organization/certificates/{certificate_id} none PHP
getCodeInterpreterSessionsUsage GET /organization/usage/code_interpreter_sessions none PHP
getCompletionsUsage GET /organization/usage/completions none PHP
getCosts GET /organization/costs none PHP
getEmbeddingsUsage GET /organization/usage/embeddings none PHP
getFileSearchCallsUsage GET /organization/usage/file_search_calls none PHP
getImagesUsage GET /organization/usage/images none PHP
getModerationsUsage GET /organization/usage/moderations none PHP
getVectorStoresUsage GET /organization/usage/vector_stores none PHP
getWebSearchCallsUsage GET /organization/usage/web_search_calls none PHP
listAdminApiKeys GET /organization/admin_api_keys none PHP
listAuditLogs GET /organization/audit_logs none PHP
listCertificates GET /organization/certificates none PHP
listGroupRoles GET /organization/groups/{group_id}/roles none PHP
listGroupUsers GET /organization/groups/{group_id}/users none PHP
listGroups GET /organization/groups none PHP
listInvites GET /organization/invites none PHP
listOrganizationRoles GET /organization/roles none PHP
listOrganizationSpendAlerts GET /organization/spend_alerts none PHP
listProjectApiKeys GET /organization/projects/{project_id}/api_keys none PHP
listProjectCertificates GET /organization/projects/{project_id}/certificates none PHP
listProjectGroupRoles GET /projects/{project_id}/groups/{group_id}/roles none PHP
listProjectGroups GET /organization/projects/{project_id}/groups none PHP
listProjectRateLimits GET /organization/projects/{project_id}/rate_limits none PHP
listProjectRoles GET /projects/{project_id}/roles none PHP
listProjectServiceAccounts GET /organization/projects/{project_id}/service_accounts none PHP
listProjectSpendAlerts GET /organization/projects/{project_id}/spend_alerts none PHP
listProjectUserRoles GET /projects/{project_id}/users/{user_id}/roles none PHP
listProjectUsers GET /organization/projects/{project_id}/users none PHP
listProjects GET /organization/projects none PHP
listUserRoles GET /organization/users/{user_id}/roles none PHP
listUsers GET /organization/users none PHP
modifyCertificate POST /organization/certificates/{certificate_id} json PHP
modifyProject POST /organization/projects/{project_id} json PHP
modifyProjectHostedToolPermissions POST /organization/projects/{project_id}/hosted_tool_permissions json PHP
modifyProjectModelPermissions POST /organization/projects/{project_id}/model_permissions json PHP
modifyProjectRateLimit POST /organization/projects/{project_id}/rate_limits/{rate_limit_id} json PHP
modifyProjectUser POST /organization/projects/{project_id}/users/{user_id} json PHP
modifyUser POST /organization/users/{user_id} json PHP
removeGroupUser DELETE /organization/groups/{group_id}/users/{user_id} none PHP
removeProjectGroup DELETE /organization/projects/{project_id}/groups/{group_id} none PHP
retrieveAdminApiKey GET /organization/admin_api_keys/{key_id} none PHP
retrieveGroup GET /organization/groups/{group_id} none PHP
retrieveGroupRole GET /organization/groups/{group_id}/roles/{role_id} none PHP
retrieveGroupUser GET /organization/groups/{group_id}/users/{user_id} none PHP
retrieveInvite GET /organization/invites/{invite_id} none PHP
retrieveOrganizationDataRetention GET /organization/data_retention none PHP
retrieveOrganizationRole GET /organization/roles/{role_id} none PHP
retrieveOrganizationSpendAlert GET /organization/spend_alerts/{alert_id} none PHP
retrieveProject GET /organization/projects/{project_id} none PHP
retrieveProjectApiKey GET /organization/projects/{project_id}/api_keys/{api_key_id} none PHP
retrieveProjectDataRetention GET /organization/projects/{project_id}/data_retention none PHP
retrieveProjectGroup GET /organization/projects/{project_id}/groups/{group_id} none PHP
retrieveProjectGroupRole GET /projects/{project_id}/groups/{group_id}/roles/{role_id} none PHP
retrieveProjectHostedToolPermissions GET /organization/projects/{project_id}/hosted_tool_permissions none PHP
retrieveProjectModelPermissions GET /organization/projects/{project_id}/model_permissions none PHP
retrieveProjectRole GET /projects/{project_id}/roles/{role_id} none PHP
retrieveProjectServiceAccount GET /organization/projects/{project_id}/service_accounts/{service_account_id} none PHP
retrieveProjectSpendAlert GET /organization/projects/{project_id}/spend_alerts/{alert_id} none PHP
retrieveProjectUser GET /organization/projects/{project_id}/users/{user_id} none PHP
retrieveProjectUserRole GET /projects/{project_id}/users/{user_id}/roles/{role_id} none PHP
retrieveUser GET /organization/users/{user_id} none PHP
retrieveUserRole GET /organization/users/{user_id}/roles/{role_id} none PHP
unassignGroupRole DELETE /organization/groups/{group_id}/roles/{role_id} none PHP
unassignProjectGroupRole DELETE /projects/{project_id}/groups/{group_id}/roles/{role_id} none PHP
unassignProjectUserRole DELETE /projects/{project_id}/users/{user_id}/roles/{role_id} none PHP
unassignUserRole DELETE /organization/users/{user_id}/roles/{role_id} none PHP
updateGroup POST /organization/groups/{group_id} json PHP
updateOrganizationDataRetention POST /organization/data_retention json PHP
updateOrganizationRole POST /organization/roles/{role_id} json PHP
updateOrganizationSpendAlert POST /organization/spend_alerts/{alert_id} json PHP
updateProjectDataRetention POST /organization/projects/{project_id}/data_retention json PHP
updateProjectRole POST /projects/{project_id}/roles/{role_id} json PHP
updateProjectServiceAccount POST /organization/projects/{project_id}/service_accounts/{service_account_id} json PHP
updateProjectSpendAlert POST /organization/projects/{project_id}/spend_alerts/{alert_id} json PHP
uploadCertificate POST /organization/certificates json PHP

Audio

SDK method HTTP route Request body Example
createSpeech POST /audio/speech json PHP
createTranscription POST /audio/transcriptions multipart PHP
createTranslation POST /audio/translations multipart PHP
createVoice POST /audio/voices multipart PHP
createVoiceConsent POST /audio/voice_consents multipart PHP
deleteVoiceConsent DELETE /audio/voice_consents/{consent_id} none PHP
listVoiceConsents GET /audio/voice_consents none PHP
retrieveVoiceConsent GET /audio/voice_consents/{consent_id} none PHP
updateVoiceConsent POST /audio/voice_consents/{consent_id} json PHP

Batches

SDK method HTTP route Request body Example
cancelBatch POST /batches/{batch_id}/cancel none PHP
createBatch POST /batches json PHP
listBatches GET /batches none PHP
retrieveBatch GET /batches/{batch_id} none PHP

Chat

SDK method HTTP route Request body Example
createChatCompletion POST /chat/completions json PHP
deleteChatCompletion DELETE /chat/completions/{completion_id} none PHP
getChatCompletion GET /chat/completions/{completion_id} none PHP
getChatMessages GET /chat/completions/{completion_id}/messages none PHP
listChatCompletions GET /chat/completions none PHP
updateChatCompletion POST /chat/completions/{completion_id} json PHP

Chatkit

SDK method HTTP route Request body Example
cancelChatKitSession POST /chatkit/sessions/{session_id}/cancel none PHP
createChatKitSession POST /chatkit/sessions json PHP
deleteChatKitThread DELETE /chatkit/threads/{thread_id} none PHP
listChatKitThreadItems GET /chatkit/threads/{thread_id}/items none PHP
listChatKitThreads GET /chatkit/threads none PHP
retrieveChatKitThread GET /chatkit/threads/{thread_id} none PHP

Containers

SDK method HTTP route Request body Example
createContainer POST /containers json PHP
createContainerFile POST /containers/{container_id}/files multipart PHP
deleteContainer DELETE /containers/{container_id} none PHP
deleteContainerFile DELETE /containers/{container_id}/files/{file_id} none PHP
listContainerFiles GET /containers/{container_id}/files none PHP
listContainers GET /containers none PHP
retrieveContainer GET /containers/{container_id} none PHP
retrieveContainerFile GET /containers/{container_id}/files/{file_id} none PHP
retrieveContainerFileContent GET /containers/{container_id}/files/{file_id}/content none PHP

Conversations

SDK method HTTP route Request body Example
createConversation POST /conversations json PHP
createConversationItems POST /conversations/{conversation_id}/items json PHP
deleteConversation DELETE /conversations/{conversation_id} none PHP
deleteConversationItem DELETE /conversations/{conversation_id}/items/{item_id} none PHP
listConversationItems GET /conversations/{conversation_id}/items none PHP
retrieveConversation GET /conversations/{conversation_id} none PHP
retrieveConversationItem GET /conversations/{conversation_id}/items/{item_id} none PHP
updateConversation POST /conversations/{conversation_id} json PHP

Embeddings

SDK method HTTP route Request body Example
createEmbedding POST /embeddings json PHP

Files

SDK method HTTP route Request body Example
deleteFile DELETE /files/{file_id} none PHP
listFiles GET /files none PHP
retrieveFile GET /files/{file_id} none PHP
retrieveFileContent GET /files/{file_id}/content none PHP
uploadFile POST /files multipart PHP

Fine Tuning

SDK method HTTP route Request body Example
cancelFineTuning (deprecated) POST /fine_tuning/jobs/{fine_tuning_job_id}/cancel none PHP
createFineTuningCheckpointPermission (deprecated) POST /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions json PHP
createFineTuningJob (deprecated) POST /fine_tuning/jobs json PHP
deleteFineTuningCheckpointPermission (deprecated) DELETE /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions/{permission_id} none PHP
listFineTuningCheckpointPermissions (deprecated) GET /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions none PHP
listFineTuningCheckpoints (deprecated) GET /fine_tuning/jobs/{fine_tuning_job_id}/checkpoints none PHP
listFineTuningEvents (deprecated) GET /fine_tuning/jobs/{fine_tuning_job_id}/events none PHP
listFineTuningJobs (deprecated) GET /fine_tuning/jobs none PHP
pauseFineTuning (deprecated) POST /fine_tuning/jobs/{fine_tuning_job_id}/pause none PHP
resumeFineTuning (deprecated) POST /fine_tuning/jobs/{fine_tuning_job_id}/resume none PHP
retrieveFineTuningJob (deprecated) GET /fine_tuning/jobs/{fine_tuning_job_id} none PHP
runFineTuningGrader (deprecated) POST /fine_tuning/alpha/graders/run json PHP
validateFineTuningGrader (deprecated) POST /fine_tuning/alpha/graders/validate json PHP

Images

SDK method HTTP route Request body Example
createImage POST /images/generations json PHP
createImageEdit POST /images/edits multipart PHP

Models

SDK method HTTP route Request body Example
deleteModel DELETE /models/{model} none PHP
listModels GET /models none PHP
retrieveModel GET /models/{model} none PHP

Moderations

SDK method HTTP route Request body Example
createModeration POST /moderations json PHP

Realtime

SDK method HTTP route Request body Example
acceptRealtimeCall POST /realtime/calls/{call_id}/accept json PHP
createRealtimeClientSecret POST /realtime/client_secrets json PHP
createRealtimeTranslationClientSecret POST /realtime/translations/client_secrets json PHP
hangupRealtimeCall POST /realtime/calls/{call_id}/hangup none PHP
referRealtimeCall POST /realtime/calls/{call_id}/refer json PHP
rejectRealtimeCall POST /realtime/calls/{call_id}/reject json PHP

Responses

SDK method HTTP route Request body Example
cancelResponse POST /responses/{response_id}/cancel none PHP
compactResponse POST /responses/compact json PHP
countResponseInputTokens POST /responses/input_tokens json PHP
createResponse POST /responses json PHP
deleteResponse DELETE /responses/{response_id} none PHP
getResponse GET /responses/{response_id} none PHP
listInputItems GET /responses/{response_id}/input_items none PHP

Skills

SDK method HTTP route Request body Example
createSkill POST /skills multipart PHP
createSkillVersion POST /skills/{skill_id}/versions multipart PHP
deleteSkill DELETE /skills/{skill_id} none PHP
deleteSkillVersion DELETE /skills/{skill_id}/versions/{version} none PHP
listSkillVersions GET /skills/{skill_id}/versions none PHP
listSkills GET /skills none PHP
retrieveSkill GET /skills/{skill_id} none PHP
retrieveSkillContent GET /skills/{skill_id}/content none PHP
retrieveSkillVersion GET /skills/{skill_id}/versions/{version} none PHP
retrieveSkillVersionContent GET /skills/{skill_id}/versions/{version}/content none PHP
updateSkill POST /skills/{skill_id} json PHP

Uploads

SDK method HTTP route Request body Example
addUploadPart POST /uploads/{upload_id}/parts multipart PHP
cancelUpload POST /uploads/{upload_id}/cancel none PHP
completeUpload POST /uploads/{upload_id}/complete json PHP
createUpload POST /uploads json PHP

Vector Stores

SDK method HTTP route Request body Example
cancelVectorStoreFileBatch POST /vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel none PHP
createVectorStore POST /vector_stores json PHP
createVectorStoreFile POST /vector_stores/{vector_store_id}/files json PHP
createVectorStoreFileBatch POST /vector_stores/{vector_store_id}/file_batches json PHP
deleteVectorStore DELETE /vector_stores/{vector_store_id} none PHP
deleteVectorStoreFile DELETE /vector_stores/{vector_store_id}/files/{file_id} none PHP
listVectorStoreFiles GET /vector_stores/{vector_store_id}/files none PHP
listVectorStoreFilesInBatch GET /vector_stores/{vector_store_id}/file_batches/{batch_id}/files none PHP
listVectorStores GET /vector_stores none PHP
modifyVectorStore POST /vector_stores/{vector_store_id} json PHP
retrieveVectorStore GET /vector_stores/{vector_store_id} none PHP
retrieveVectorStoreFile GET /vector_stores/{vector_store_id}/files/{file_id} none PHP
retrieveVectorStoreFileBatch GET /vector_stores/{vector_store_id}/file_batches/{batch_id} none PHP
retrieveVectorStoreFileContent GET /vector_stores/{vector_store_id}/files/{file_id}/content none PHP
searchVectorStore POST /vector_stores/{vector_store_id}/search json PHP
updateVectorStoreFileAttributes POST /vector_stores/{vector_store_id}/files/{file_id} json PHP

Custom API Origin

origin accepts either a hostname or an absolute base URL. A hostname uses /v1; an absolute URL keeps its path unless basePath is supplied explicitly.

$openAI = new OpenAI(
    requestFactory: $factory,
    streamFactory: $factory,
    uriFactory: $factory,
    httpClient: new Client(['stream' => true]),
    apiKey: (string) getenv('OPENAI_API_KEY'),
    origin: 'https://gateway.example/openai/v1',
);

Deprecated And Removed APIs

Version 4 deliberately does not expose APIs that OpenAI classifies as legacy, has already removed, or has scheduled for shutdown: classic Completions, Assistants/Threads/Runs/Messages, Realtime Beta session creation, Evals, Videos, and DALL-E image variations. Use Responses and Conversations instead of Assistants.

The self-serve fine-tuning routes remain temporarily available and are marked deprecated because eligible existing customers can still use them during OpenAI's transition. See OpenAI's deprecation schedule and the v4 migration notes before upgrading.

Development

composer test
composer analyse
vendor/bin/php-cs-fixer fix --dry-run --diff
composer audit

License

ISC