PHP SDK
The official PHP library for the RSFlowHub AI API. Add sentiment analysis, translation, chat, PII redaction, review and ticket AI, knowledge-base search and chatbots to Laravel or any PHP 8.1+ app.
Direct System Definition: RSFlowHub PHP SDK
rsflowhub/rsflowhub-php is the official Composer package for RSFlowHub. Install it with composer require rsflowhub/rsflowhub-php, set RSFLOWHUB_API_KEY and call any API as $client->ai->slugInCamelCase([...]). It needs PHP 8.1+, throws typed exceptions by error code, retries 429 and 5xx answers, uploads files, and includes a Laravel service provider and facade. New APIs work without updating the package.
| Package | rsflowhub/rsflowhub-php on Packagist |
|---|---|
| Install | composer require rsflowhub/rsflowhub-php |
| Requires | PHP 8.1 or newer, Guzzle 7 |
| Works with | Laravel, Symfony, WordPress, any PHP app |
| Source | github.com/RSFlowHub/rsflowhub-php (MIT license) |
Install
composer require rsflowhub/rsflowhub-php
Create an API key in your dashboard and put it in your environment (for Laravel, your .env). The SDK reads RSFLOWHUB_API_KEY automatically, or you can pass the key to the constructor.
RSFLOWHUB_API_KEY=rfh_your_api_key
Your API key spends your credits. Keep it in server configuration and never print it into HTML or JavaScript. Browser code should call your PHP backend, which calls RSFlowHub.
Make your first call
<?php
require 'vendor/autoload.php';
use RSFlowHub\RSFlowHub;
$client = new RSFlowHub(); // reads RSFLOWHUB_API_KEY
$res = $client->ai->sentimentAnalysis([
'text' => 'Setup took two minutes and support answered right away.',
]);
echo $res->result('sentiment'); // "positive"
print_r($res->result()); // the whole AI output
echo $res->requestId; // "req_..." quote it when you contact support
The response object
Every successful call returns a read-only RSFlowHub\Response built from the API envelope {success, request_id, data, meta}. AI endpoints put their output in data.result.
| Use | What you get |
|---|---|
$res->result() | The AI output (data.result), or data when there is no result (knowledge bases, chatbots) |
$res->result('aspects.0.name') | One value from the output, with dot notation |
$res['key'], $res->key, $res->get('a.b'), $res->toArray() | Anything under data |
$res->requestId, $res->meta | Server request id and {version, timestamp} |
$res->status(), $res->header('X-Request-Id') | HTTP status and headers |
$res->rateLimit() | ['limit', 'remaining', 'reset'] from the X-RateLimit-* headers |
Calling any API
Methods are not hard-coded. The method is the endpoint's slug in camelCase, grouped by resource: $client->ai, $client->knowledgeBases, $client->chatbots, $client->faqCollections and $client->account. See every endpoint in the API reference.
// The method name is the endpoint slug in camelCase
$client->ai->translation(['text' => 'Hello', 'target_language' => 'French']);
$client->ai->piiRedaction(['text' => 'Call me on 555-0100']);
$client->ai->ticketAnalyze(['ticket' => 'My order never arrived']);
// An AI API released after you installed the SDK works the same way
$client->ai->brandNewEndpoint(['text' => '...']);
// A resource the SDK does not know yet
$client->resource('webhooks')->list();
// Any route, any method
$usage = $client->request('GET', '/account/usage', [], ['page' => 2]);
Path ids and file uploads
// Ids in the URL come first, then the body
$client->knowledgeBases->ask(12, ['question' => 'Refund policy?']);
$client->chatbots->getConversation(3, 'conv_abc123');
// ...or by name inside the array
$client->knowledgeBases->ask(['id' => 12, 'question' => 'Refund policy?']);
// A file value (SplFileInfo, fopen() resource, PSR-7 stream) makes it an upload
$client->knowledgeBases->createDocument(12, [
'file' => new SplFileInfo(__DIR__ . '/refund-policy.pdf'),
'metadata' => ['source' => 'help-center'], // sent as metadata[source]
]);
Knowledge bases (RAG) and chatbots
Build a searchable help center from your documents and FAQs, then answer questions from it or run a chatbot on top of it.
// 1. A knowledge base for your help center
$kb = $client->knowledgeBases->create(['name' => 'Help center']);
$kbId = $kb->result('knowledge_base.id');
// 2. Add content: a document, or a single FAQ item
$client->knowledgeBases->createDocument($kbId, ['file' => new SplFileInfo('refund-policy.pdf')]);
$client->knowledgeBases->createItem($kbId, [
'content' => 'How long do refunds take?',
'answer' => 'Refunds reach your card in 5 to 7 business days.',
]);
// 3. Ask questions grounded in that content
$answer = $client->knowledgeBases->ask($kbId, ['question' => 'When will I get my money back?']);
print_r($answer->result());
// A chatbot (created in the dashboard or with $client->chatbots->create([...]))
$reply = $client->chatbots->sendMessage($chatbotId, ['message' => 'Where is my order?']);
$conversationId = $reply->result('conversation_id');
Errors
Every API error is thrown as an exception that extends RSFlowHub\Exceptions\ApiException, chosen by the error code in the error envelope. All of them have getErrorCode(), getMessage(), getStatus(), getDetails() and getRequestId().
use RSFlowHub\Exceptions\ApiException;
use RSFlowHub\Exceptions\ConnectionException;
use RSFlowHub\Exceptions\InsufficientCreditsException;
use RSFlowHub\Exceptions\RateLimitException;
use RSFlowHub\Exceptions\ValidationException;
try {
$res = $client->ai->textSummarize(['text' => $article]);
} catch (ValidationException $e) {
print_r($e->getErrors()); // ['text' => ['The text field is required.']]
} catch (InsufficientCreditsException $e) {
echo "Need {$e->getRequiredCredits()} credits, have {$e->getAvailableCredits()}.";
} catch (RateLimitException $e) {
sleep($e->getRetryAfter() ?? 1); // already retried max_retries times
} catch (ApiException $e) {
echo $e->getErrorCode(), ': ', $e->getMessage(), ' (', $e->getRequestId(), ')';
} catch (ConnectionException $e) {
// DNS, TLS, timeout or connection refused
}
| Exception | Status | Error codes | Extra |
|---|---|---|---|
AuthenticationException | 401 | API_KEY_MISSING, INVALID_API_KEY | |
InsufficientCreditsException | 402 | INSUFFICIENT_CREDITS | getRequiredCredits(), getAvailableCredits() |
PermissionDeniedException | 403 | SPENDING_LIMIT_REACHED, USER_INACTIVE | |
NotFoundException | 404 | ENDPOINT_NOT_FOUND | |
ValidationException | 422 | VALIDATION_ERROR | getErrors() |
RateLimitException | 429 | RATE_LIMIT_EXCEEDED | getRetryAfter() |
ServerException | 500 | INTERNAL_SERVER_ERROR | |
ServiceUnavailableException | 502 / 503 | AI_PROVIDER_ERROR, PROVIDER_UNAVAILABLE | |
ConnectionException | none | DNS, TLS, timeout |
Options, retries and timeouts
429, 502, 503, 504 and connection failures are retried twice with backoff, respecting Retry-After; those answers are never charged. Other errors are thrown at once. Limits and the credit formula are on Rate limits & credits.
$client = new RSFlowHub('rfh_your_api_key', [
'base_url' => 'https://rsflowhub.com/api/v1', // or RSFLOWHUB_BASE_URL
'timeout' => 60, // seconds per attempt
'max_retries' => 2, // for 429, 502, 503, 504 and connection errors
'headers' => [], // extra headers on every request
'http_client' => null, // your own GuzzleHttp\ClientInterface (proxy, logging, tests)
'live_spec' => true, // look up unknown non-AI methods in the live OpenAPI document
]);
$res->rateLimit(); // ['limit' => 60, 'remaining' => 59, 'reset' => null]
Laravel
Laravel discovers the service provider and the RSFlowHub facade automatically. Add your settings to config/services.php:
// config/services.php
'rsflowhub' => [
'key' => env('RSFLOWHUB_API_KEY'),
'base_url' => env('RSFLOWHUB_BASE_URL', 'https://rsflowhub.com/api/v1'),
'timeout' => 60,
'max_retries' => 2,
],
Then use the facade, or inject the client (it is registered as a singleton):
use RSFlowHub\Laravel\Facades\RSFlowHub;
use RSFlowHub\RSFlowHub as Client;
use RSFlowHub\Exceptions\ValidationException;
class ReviewController extends Controller
{
// Facade
public function store(Request $request)
{
$spam = RSFlowHub::ai()->spamDetection(['text' => $request->input('review')]);
if ($spam->result('is_spam')) {
return back()->withErrors(['review' => 'This looks like spam.']);
}
// ...
}
// Or inject the client (it is a singleton)
public function summary(Client $client, Product $product)
{
return $client->ai->reviewSummary([
'reviews' => $product->reviews()->pluck('body')->take(50)->all(),
])->result();
}
}
For longer calls (ticket triage, summaries of many reviews), run them in a queued job so web requests stay fast:
// app/Jobs/TriageTicket.php: run AI calls in a queued job, not in the web request
class TriageTicket implements ShouldQueue
{
use Queueable;
public function __construct(public Ticket $ticket) {}
public function handle(\RSFlowHub\RSFlowHub $client): void
{
$analysis = $client->ai->ticketAnalyze(['ticket' => $this->ticket->body]);
$this->ticket->update([
'priority' => $analysis->result('priority'),
'department' => $analysis->result('suggested_department'),
]);
}
}
Autocomplete and staying up to date
- New AI APIs work at once: they are called by name, no upgrade needed.
- Other new routes are looked up in the public OpenAPI document the first time you call them.
- IDE autocomplete:
$client->ai,$client->knowledgeBasesand the other resources carry generated@methodtypes with every parameter. They are regenerated weekly from the OpenAPI document;composer update rsflowhub/rsflowhub-phppicks them up. - The full method list is in docs/ENDPOINTS.md.
Related
- All official SDKs and how they stay up to date
- Error codes and rate limits & credits
- Authentication & API keys
- OpenAPI document (every request and response)
- Examples repository
- RSFlowHub JavaScript & TypeScript SDK (
npm install rsflowhub) - RSFlowHub Python SDK (
pip install rsflowhub)