Search by

rodiumai / laravel-sdk

lecodeur228

Laravel/PHP SDK for the RodiumAI API — multi-model AI with Mobile Money payments

v0.1.2 2026-06-12 15:54 UTC

This package is auto-updated.

Last update: 2026-08-31 14:14:49 UTC


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.

Latest Version on Packagist Total Downloads PHP Version License: MIT Tests

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

  • PHP 8.1+ with the json extension
  • Laravel 10–13 (optional — RodiumAIClient works 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.