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)).