rodiumai / laravel-sdk
Laravel/PHP SDK for the RodiumAI API — multi-model AI with Mobile Money payments
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0
- illuminate/support: ^8.0|^9.0|^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- guzzlehttp/psr7: ^2.0
- orchestra/testbench: ^6.0|^7.0|^8.0|^9.0|^10.0|^11.0
- phpunit/phpunit: ^9.0|^10.0|^11.0|^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Official PHP / Laravel SDK for the Rodium AI API — unified access to AI models (OpenAI, Anthropic, Google, DeepSeek…) with RODI credit billing and Mobile Money top-ups.
OpenAI-compatible REST API: same endpoints and payloads as documented at rodiumai.io/docs.
Links
| Resource | URL |
|---|---|
| Packagist | packagist.org/packages/rodiumai/laravel-sdk |
| Source code | github.com/Docteur-Parfait/rodiumai-laravel-sdk |
| Laravel SDK guide | rodiumai.io/docs/guides/laravel-sdk |
| API documentation | rodiumai.io/docs |
| Dashboard & API keys | rodiumai.io/dashboard |
Table of contents
- Requirements
- Installation
- Configuration
- Quick start
- Chat completions
- Streaming & real-time chat (SSE)
- Models catalogue
- Embeddings
- Images (
POST /v1/images/generations) - Videos (
POST /v1/videos/generations) - Audio
- Anthropic Messages
- Wallet & pricing
- Error handling
- SDK reference
- Local development
- Migration 0.1.x → 0.2.0
- Testing
- License
Requirements
- PHP 8.1+ with the
jsonextension - Laravel 10–13 (optional —
RodiumAIClientworks in plain PHP) - Rodium AI account + API key (
rd_sk_…): dashboard
Installation
composer require rodiumai/laravel-sdk:^0.3
Publish config (optional):
php artisan vendor:publish --tag=rodiumai-config
The ServiceProvider and RodiumAI Facade are auto-discovered.
Configuration
.env:
RODIUMAI_API_KEY=rd_sk_your_secret_key RODIUMAI_BASE_URL=https://api.rodiumai.io/v1 RODIUMAI_DEFAULT_MODEL=openai/gpt-4o RODIUMAI_TIMEOUT=30 # RODIUMAI_LOCALE=fr # optional — SDK error hints (en, fr, es)
| Variable | Default | Description |
|---|---|---|
RODIUMAI_API_KEY |
— | Secret key from the dashboard |
RODIUMAI_BASE_URL |
https://api.rodiumai.io/v1 |
Gateway base URL (use http://localhost:8001/v1 locally) |
RODIUMAI_DEFAULT_MODEL |
openai/gpt-4o |
Default model slug |
RODIUMAI_TIMEOUT |
30 |
HTTP timeout in seconds |
RODIUMAI_LOCALE |
en |
Localized exception hints |
Never commit .env or API keys.
Quick start
Laravel (Facade)
use RodiumAI\Facades\RodiumAI; $response = RodiumAI::model('openai/gpt-4o') ->temperature(0.7) ->maxTokens(300) ->chat('Explain Rodium AI in two sentences.'); echo $response->content; echo $response->costRodi(); // RODI cost from usage.cost_rodi
Plain PHP
use RodiumAI\RodiumAIClient; $client = new RodiumAIClient(apiKey: getenv('RODIUMAI_API_KEY')); $response = $client->chat('Hello!'); echo $response->content;
Chat completions
POST /v1/chat/completions — OpenAI-compatible. All OpenAI fields pass-through (tools, response_format, …).
Parameters
| Parameter | Required | Description |
|---|---|---|
model |
yes | Catalogue slug or smart alias (rodiumai/smart, rodium/fast, …) |
messages |
yes | String, ChatMessage objects, or arrays |
max_tokens, temperature, top_p |
no | Decoding |
stream |
no | SSE streaming |
tools, tool_choice |
no | Function calling |
response_format |
no | JSON mode / schema |
session_id |
no | Custom models memory |
use RodiumAI\Data\ChatMessage; $messages = [ ChatMessage::system('You are a Laravel assistant.'), ChatMessage::user('What is a Service Provider?'), ]; $response = RodiumAI::model('openai/gpt-4o') ->temperature(0.5) ->maxTokens(500) ->chat($messages, [ 'tools' => [/* OpenAI tool definitions */], 'response_format' => ['type' => 'json_object'], ]); echo $response->content; echo $response->costRodi();
Multi-turn conversation
$history = [ ChatMessage::user('My name is Amina.'), ChatMessage::assistant('Nice to meet you, Amina!'), ChatMessage::user('What is my name?'), ]; $response = RodiumAI::chat($history);
Multimodal vision
$b64 = base64_encode(file_get_contents('invoice.png')); $response = RodiumAI::chat([[ 'role' => 'user', 'content' => [ ['type' => 'text', 'text' => 'Extract the total amount.'], ['type' => 'image_url', 'image_url' => ['url' => "data:image/png;base64,{$b64}"]], ], ]], ['model' => 'openai/gpt-4o']);
HTTP(S) image URLs work in chat (not in image/video generation).
Function calling
$response = RodiumAI::chat('Weather in Lomé?', [ 'model' => 'openai/gpt-4o', 'tools' => [[ 'type' => 'function', 'function' => [ 'name' => 'get_weather', 'parameters' => [ 'type' => 'object', 'properties' => ['city' => ['type' => 'string']], 'required' => ['city'], ], ], ]], 'tool_choice' => 'auto', ]);
Smart routing
| Alias | Behavior |
|---|---|
rodiumai/smart |
LLM router — metadata in $response->routing() |
rodium/fast, rodium/pro, … |
Rule-based profiles |
$response = RodiumAI::model('rodiumai/smart')->chat('Summarize RODI credits.'); $routing = $response->routing();
See Smart routing guide.
Streaming & real-time chat (SSE)
No WebSocket — real-time discussion uses SSE only.
foreach (RodiumAI::model('openai/gpt-4o')->stream('Tell a short story.') as $delta) { echo $delta; }
Real-time chat loop
$history = []; $ask = function (string $userText) use (&$history) { $history[] = ChatMessage::user($userText); $parts = ''; foreach (RodiumAI::stream($history) as $delta) { echo $delta; // push to UI $parts .= $delta; } $history[] = ChatMessage::assistant($parts); return $parts; }; $ask('Bonjour!'); $ask('Rappelle-moi ma première question.');
Laravel StreamedResponse
return response()->stream(function () { foreach (RodiumAI::stream('Hello') as $delta) { echo 'data: ' . json_encode(['delta' => $delta]) . "\n\n"; ob_flush(); flush(); } echo "data: [DONE]\n\n"; }, 200, ['Content-Type' => 'text/event-stream', 'Cache-Control' => 'no-cache']);
Models catalogue
$catalogue = RodiumAI::models(); $catalogue->ids(); $catalogue->chatModels(); $catalogue->byProvider('anthropic'); $catalogue->findById('openai/gpt-4o'); $info = RodiumAI::modelInfo('openai/gpt-4o'); $info->contextWindow; $info->pricing(); $coding = RodiumAI::codingModels();
Each model includes rodiumai_pricing, rodiumai_capabilities (modalities, streaming, tools, vision).
Embeddings
POST /v1/embeddings
$response = RodiumAI::embeddings('Hello world', [ 'model' => 'openai/text-embedding-3-small', ]); $vector = $response->firstEmbedding(); // Batch $response = RodiumAI::embeddings(['Sentence A', 'Sentence B'], [ 'model' => 'openai/text-embedding-3-small', ]);
Images (POST /v1/images/generations)
| Parameter | Required | Notes |
|---|---|---|
model, prompt |
yes | |
n |
no | 1–10 (Imagen max 4) |
size |
no | 1024x1024, 1536x1024, … |
quality |
no | Affects RODI quote |
aspect_ratio |
no | Gemini |
image, images |
no | i2i — up to 14 refs |
mask |
no | OpenAI inpainting |
Reference images: base64, data URL, or gs:// — no remote HTTP fetch.
Text-to-image
$image = RodiumAI::images([ 'model' => 'openai/gpt-image-1', 'prompt' => 'A red fox in the snow', 'size' => '1024x1024', 'quality' => 'medium', ]); $b64 = $image->firstB64();
Image-to-image
$ref = base64_encode(file_get_contents('product.png')); $image = RodiumAI::images([ 'model' => 'google/gemini-3.1-flash-image', 'prompt' => 'Soft white studio background', 'image' => ['b64_json' => $ref, 'mime_type' => 'image/png'], ]);
Inpainting
$image = RodiumAI::images([ 'model' => 'openai/gpt-image-1', 'prompt' => 'Replace sky with sunset', 'image' => ['b64_json' => $sourceB64], 'mask' => ['b64_json' => $maskB64], ]);
Videos (POST /v1/videos/generations)
Always pass 'timeout' => 600 — jobs can take minutes.
| Parameter | Required | Notes |
|---|---|---|
model, prompt |
yes | |
duration_seconds |
no | Default 8; Sora → 4/8/12 s |
aspect_ratio, size |
no | Sora layout |
image |
no | Start frame (image→video) |
last_frame |
no | End frame (Veo interpolation) |
Text-to-video
$video = RodiumAI::videos([ 'model' => 'google/veo-3.1-generate-preview', 'prompt' => 'Ocean waves at golden hour', 'duration_seconds' => 8, 'timeout' => 600, ]);
Image-to-video
$frame = base64_encode(file_get_contents('storyboard.png')); $video = RodiumAI::videos([ 'model' => 'google/veo-3.1-generate-preview', 'prompt' => 'Subtle pulse animation', 'duration_seconds' => 8, 'image' => ['b64_json' => $frame, 'mime_type' => 'image/png'], 'timeout' => 600, ]);
Interpolation (Veo)
$video = RodiumAI::videos([ 'model' => 'google/veo-3.1-generate-preview', 'prompt' => 'Smooth morph between frames', 'image' => ['b64_json' => $startB64], 'last_frame' => ['b64_json' => $endB64], 'timeout' => 600, ]);
Audio
Transcriptions — multipart
| Parameter | Required | Notes |
|---|---|---|
file |
yes | File path |
model |
yes | |
language |
no | ISO-639-1 (fr, en) |
prompt |
no | Style hint |
response_format |
no | json, text, verbose_json |
$transcript = RodiumAI::transcribe('/path/to/audio.mp3', [ 'model' => 'google/gemini-2.5-flash', 'language' => 'fr', ]); echo $transcript->text;
Speech — binary response
| Parameter | Required | Notes |
|---|---|---|
model, input |
yes | |
voice |
no | alloy, echo, fable, onyx, nova, shimmer |
response_format |
no | mp3, opus, wav, pcm |
speed |
no | 0.25–4.0 |
$audioBytes = RodiumAI::speech([ 'model' => 'openai/tts-1', 'input' => 'Hello from RodiumAI', 'voice' => 'nova', 'response_format' => 'mp3', ]); file_put_contents('speech.mp3', $audioBytes);
Anthropic Messages
POST /v1/messages
$response = RodiumAI::messages([ 'model' => 'anthropic/claude-sonnet-4-6', 'max_tokens' => 1024, 'system' => 'You are concise.', 'messages' => [ ['role' => 'user', 'content' => 'Explain RODI credits.'], ], ]); echo $response->content;
Streaming: 'stream' => true — Anthropic SSE events.
Wallet & pricing
$wallet = RodiumAI::wallet(); echo $wallet->balanceRodi; $pricing = RodiumAI::pricing(); $pricing->findByModel('openai/gpt-4o');
Error handling
See docs/api/errors.
| HTTP | Exception | Notes |
|---|---|---|
| 401 | UnauthorizedException |
Invalid or missing API key |
| 402 | InsufficientCreditsException |
Top up RODI in dashboard |
| 403 | ForbiddenException |
Scope or model whitelist |
| 404 | NotFoundException |
Unknown model or resource |
| 422 | ValidationException |
Invalid request body |
| 429 | RateLimitException |
Use $e->retryAfter() for backoff |
| Other | RodiumAIException |
$e->errorCode(), $e->responseBody() |
use RodiumAI\Exceptions\InsufficientCreditsException; use RodiumAI\Exceptions\RateLimitException; use RodiumAI\Facades\RodiumAI; try { RodiumAI::chat('Test'); } catch (InsufficientCreditsException $e) { logger()->warning('Insufficient RODI', ['code' => $e->errorCode()]); } catch (RateLimitException $e) { sleep($e->retryAfter() ?? 30); }
SDK reference
| Method | Returns | Gateway route |
|---|---|---|
chat($messages, $options) |
ChatResponse |
POST /v1/chat/completions |
stream($messages, $options) |
Generator<string> |
POST /v1/chat/completions (SSE) |
models() |
ModelCollection |
GET /v1/models |
modelInfo($id) |
ModelInfo |
GET /v1/models/{id} |
codingModels() |
ModelCollection |
GET /v1/models/coding |
embeddings($input, $options) |
EmbeddingResponse |
POST /v1/embeddings |
images($options) |
ImageResponse |
POST /v1/images/generations |
videos($options) |
VideoResponse |
POST /v1/videos/generations |
transcribe($filePath, $options) |
TranscriptionResponse |
POST /v1/audio/transcriptions |
speech($options) |
string (bytes) |
POST /v1/audio/speech |
messages($options) |
MessageResponse |
POST /v1/messages |
wallet() |
WalletResponse |
GET /v1/wallet |
pricing($model?) |
PricingCollection |
GET /v1/pricing |
Fluent builder: model(), temperature(), topP(), maxTokens(), systemPrompt(), language().
DTOs: ChatResponse, ChatMessage, ModelInfo, ModelCollection, EmbeddingResponse, ImageResponse, VideoResponse, TranscriptionResponse, MessageResponse, WalletResponse, PricingCollection.
Technical mapping: docs/api-alignment.md.
Local development
Point the SDK at a local gateway (e.g. Docker Compose on port 8001):
RODIUMAI_BASE_URL=http://localhost:8001/v1 RODIUMAI_API_KEY=rd_sk_dev_...
Migration 0.1.x → 0.2.0
| Change | Action |
|---|---|
base_url restored |
Set RODIUMAI_BASE_URL if not using production |
| Static enums removed | Use models() / ModelCollection for catalogue |
ModelInfo::contextWindow |
Now reads rodiumai_capabilities.context_window (gateway shape) |
| New methods | embeddings, images, videos, transcribe, speech, messages, wallet, pricing |
Require ^0.2 in composer.json.
Testing
composer install composer test # PHPUnit (mocked HTTP) export RODIUMAI_API_KEY="rd_sk_..." php bin/smoke-test.php # Live API walkthrough
License
MIT — see LICENSE.