1. Environment
# .env
VERIFAI_BASE_URL=https://verifai.iqtbots.ai
VERIFAI_API_KEY=vf_test_your_secret_here
VERIFAI_COLLECTION_ID=your-collection-uuid
// config/services.php
'verifai' => [
'base_url' => env('VERIFAI_BASE_URL'),
'api_key' => env('VERIFAI_API_KEY'),
'collection_id' => env('VERIFAI_COLLECTION_ID'),
],
2. Service class
<?php
namespace App\Services;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Http;
class VerifaiClient
{
public function enroll(string $externalId, UploadedFile $image, ?string $displayName = null): array
{
$response = Http::withToken(config('services.verifai.api_key'))
->attach('image', file_get_contents($image->getRealPath()), $image->getClientOriginalName())
->post($this->url('/api/v1/collections/' . config('services.verifai.collection_id') . '/persons/'), [
'external_id' => $externalId,
'display_name' => $displayName,
]);
return $response->json();
}
public function verify(string $externalId, UploadedFile $image, float $threshold = 0.4): array
{
$response = Http::withToken(config('services.verifai.api_key'))
->attach('image', file_get_contents($image->getRealPath()), $image->getClientOriginalName())
->post($this->url('/api/v1/verify/'), [
'collection_id' => config('services.verifai.collection_id'),
'external_id' => $externalId,
'threshold' => $threshold,
]);
return $response->json();
}
private function url(string $path): string
{
return rtrim(config('services.verifai.base_url'), '/') . $path;
}
}
3. Enroll on registration
// app/Http/Controllers/Auth/RegisteredUserController.php (after user create)
$verifai = app(\App\Services\VerifaiClient::class);
$result = $verifai->enroll(
externalId: (string) $user->id,
image: $request->file('face_photo'),
displayName: $user->name,
);
if (! ($result['success'] ?? false)) {
// handle $result['error']['code'] e.g. no_face_detected
}
4. Verify on login
$result = $verifai->verify(
externalId: (string) $user->id,
image: $request->file('face_photo'),
);
if ($result['success'] && ($result['data']['matched'] ?? false)) {
// allow login
} else {
// reject — check error.code or matched === false
}
5. Error handling
Check $result['success'] and $result['error']['code']. Common codes: no_face_detected, person_not_found, not_enrolled, rate_limit_exceeded.
Use AI-assisted setup to generate controllers, form requests, and tests from this guide.