SDK quickstart: PHP
The community-maintained openai-php/client library targets the OpenAI shape and works against our endpoint. Compatible with Laravel, Symfony, or vanilla PHP 8.
Install
composer require openai-php/client
Hello world
<?php
require __DIR__ . "/vendor/autoload.php";
$client = OpenAI::factory()
->withBaseUri("https://api.greenjoules.cloud/v1")
->withApiKey(getenv("JC_API_KEY"))
->make();
$response = $client->chat()->create([
"model" => "auto",
"messages" => [
["role" => "user", "content" => "hi"],
],
]);
echo $response->choices[0]->message->content;
Streaming
$stream = $client->chat()->createStreamed([
"model" => "auto",
"messages" => [["role" => "user", "content" => "tell a story"]],
]);
foreach ($stream as $chunk) {
echo $chunk->choices[0]->delta->content ?? "";
}
Laravel integration
// config/services.php
return [
"joule_cloud" => [
"key" => env("JC_API_KEY"),
"base_uri" => "https://api.greenjoules.cloud/v1",
],
];
// app/Providers/AppServiceProvider.php
public function register(): void
{
$this->app->singleton(\OpenAI\Client::class, fn () =>
OpenAI::factory()
->withBaseUri(config("services.joule_cloud.base_uri"))
->withApiKey(config("services.joule_cloud.key"))
->make()
);
}
// in a controller
public function ask(Request $req, OpenAI\Client $jc)
{
$r = $jc->chat()->create([
"model" => "auto",
"messages" => [["role" => "user", "content" => $req->input("q")]],
]);
return ["answer" => $r->choices[0]->message->content];
}
Joule headers
The community client wraps HTTP under the hood but doesn't fully expose raw response headers. The reliable workaround: pull headers via Guzzle directly for that call, or look up the same data via the receipt API:
$receipt = $jc->receipts()->retrieve($response->id);
echo "joules: " . $receipt->energy->total_joules;
Errors
use OpenAI\Exceptions\ErrorException;
try {
$client->chat()->create([...]);
} catch (ErrorException $e) {
if ($e->getCode() === 402) { /* low balance */ }
if ($e->getCode() === 429) { /* energy budget */ }
}