04 โ Laravel backend integration
Mint tokens and manage rooms from your Laravel app using the built-in HTTP client (no extra package required).
1. Configuration
# .env
ARZBRIDGE_BASE_URL=https://calls.arzbridge.com/api/v1
ARZBRIDGE_API_KEY=YOUR_API_KEY
ARZBRIDGE_API_SECRET=YOUR_API_SECRET
// config/services.php
'arzbridge' => [
'base_url' => env('ARZBRIDGE_BASE_URL', 'https://calls.arzbridge.com/api/v1'),
'key' => env('ARZBRIDGE_API_KEY'),
'secret' => env('ARZBRIDGE_API_SECRET'),
],
2. A service class (app/Services/ArzbridgeCalls.php)
<?php
namespace App\Services;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Http;
class ArzbridgeCalls
{
protected function client(): PendingRequest
{
return Http::baseUrl(config('services.arzbridge.base_url'))
->withToken(config('services.arzbridge.key').':'.config('services.arzbridge.secret'))
->acceptJson()
->asJson()
->retry(3, 300, throw: false);
}
/** Mint a join token for a participant. */
public function createToken(array $opts): array
{
return $this->client()->post('/tokens', $opts)->throw()->json('data');
}
public function createRoom(array $opts): array
{
return $this->client()->post('/rooms', $opts)->throw()->json('data');
}
public function listParticipants(string $room): array
{
return $this->client()->get("/rooms/".rawurlencode($room)."/participants")->throw()->json('data');
}
public function removeParticipant(string $room, string $identity): array
{
return $this->client()
->delete("/rooms/".rawurlencode($room)."/participants/".rawurlencode($identity))
->throw()->json('data');
}
public function endRoom(string $room): array
{
return $this->client()->delete("/rooms/".rawurlencode($room))->throw()->json('data');
}
public function sendData(string $room, string $data, array $opts = []): array
{
return $this->client()->post("/rooms/".rawurlencode($room)."/data", ['data' => $data] + $opts)
->throw()->json('data');
}
}
3. A controller your app calls
<?php
namespace App\Http\Controllers;
use App\Services\ArzbridgeCalls;
use Illuminate\Http\Request;
class CallController extends Controller
{
public function __construct(protected ArzbridgeCalls $calls) {}
// POST /api/calls/join โ protect with your own auth (Sanctum, session, etc.)
public function join(Request $request)
{
$data = $request->validate([
'room_id' => ['required', 'string'],
]);
$user = $request->user(); // your authenticated user
$result = $this->calls->createToken([
'room' => 'room-'.$data['room_id'],
'identity' => 'user-'.$user->id,
'name' => $user->name,
'ttl' => 3600,
'metadata' => ['role' => $user->role ?? 'member'],
// 'can_publish' => false, // e.g. a webinar viewer
]);
return response()->json([
'token' => $result['token'],
'wsUrl' => $result['ws_url'],
]);
}
}
// routes/api.php
use App\Http\Controllers\CallController;
Route::middleware('auth:sanctum')->post('/calls/join', [CallController::class, 'join']);
Your Flutter/web app calls POST /api/calls/join and receives { token, wsUrl }.
4. Server-side controls
$calls = app(\App\Services\ArzbridgeCalls::class);
$calls->removeParticipant('room-42', 'user-99'); // kick
$calls->endRoom('room-42'); // end for everyone
$calls->sendData('room-42', json_encode(['type' => 'start']), ['topic' => 'signals']);
$people = $calls->listParticipants('room-42'); // who's connected
5. Error handling
->throw() raises Illuminate\Http\Client\RequestException on non-2xx. Inspect:
use Illuminate\Http\Client\RequestException;
try {
$token = $this->calls->createToken([...]);
} catch (RequestException $e) {
$status = $e->response->status(); // 401/403/422/429/5xx
$error = $e->response->json('error'); // { code, message, fields? }
// 422 -> validation; 429 -> back off (Retry-After); 5xx -> already retried 3x
report($e);
return response()->json(['error' => $error['message'] ?? 'call service error'], $status);
}
The client above already retries transient failures (->retry(3, 300)).