PHP SDK

Available PHP 8.1+ Zero dependencies

The PHP SDK (xident/xident-php) provides a clean, modern PHP 8.1+ client for server-side age verification. Zero external dependencies — uses native cURL. Works with Laravel, Symfony, WordPress, and standalone PHP.

Secret key required: Always use your secret key (sk_live_...) for the PHP SDK. The public key (pk_live_...) is for the JS SDK only. The SDK sends it via the X-API-Key header (not Authorization: Bearer).

Installation

composer require xident/xident-php

Or without Composer: require_once '/path/to/xident-php/autoload.php';

Quick Start

Step 1: Create an init token and redirect the user to the verification widget:

<?php

use Xident\SDK\Client;

$xident = new Client(apiKey: $_ENV['XIDENT_SECRET_KEY']);

// 1. Create init token — redirect user to verification widget
$session = $xident->verification()->init([
    'callback_url' => 'https://yoursite.com/verify-callback',
    'min_age'      => 18,
    'success_url'  => 'https://yoursite.com/welcome',
    'failed_url'   => 'https://yoursite.com/sorry',
]);

header('Location: ' . $session->verifyUrl);
exit;

Step 2: After the user completes verification, they are redirected back with a ?token=xtk_xxx parameter. Always verify server-side — never trust URL parameters alone:

<?php

// 2. After user returns — verify result server-side
$token = $_GET['token']; // from callback URL ?token=xtk_xxx

$result = $xident->verification()->getResult($token);

if ($result->isVerified()) {
    echo "Age bracket: " . $result->ageBracket(); // 18
    echo "Method: " . $result->method();           // "ml_fast"
    // Grant access to age-restricted content
}

Laravel Example

<?php
// app/Http/Controllers/VerificationController.php

use Xident\SDK\Client;

class VerificationController extends Controller
{
    public function start(Request $request)
    {
        $xident = new Client(apiKey: config('services.xident.secret_key'));

        $session = $xident->verification()->init([
            'callback_url' => route('verify.callback'),
            'min_age'      => 18,
            'user_id'      => (string) $request->user()->id,
        ]);

        return redirect($session->verifyUrl);
    }

    public function callback(Request $request)
    {
        $xident = new Client(apiKey: config('services.xident.secret_key'));
        $result = $xident->verification()->getResult($request->input('token'));

        if ($result->isVerified()) {
            $request->user()->update(['age_verified' => true]);
            return redirect()->route('dashboard');
        }

        return redirect()->route('verify.failed');
    }
}

Symfony Example

<?php
// src/Controller/VerificationController.php

use Xident\SDK\Client;

class VerificationController extends AbstractController
{
    #[Route('/verify/callback')]
    public function callback(Request $request): Response
    {
        $xident = new Client(apiKey: $this->getParameter('xident_secret'));
        $result = $xident->verification()->getResult($request->query->get('token'));

        if ($result->isVerified()) {
            $request->getSession()->set('age_verified', true);
            return $this->redirectToRoute('dashboard');
        }

        return $this->redirectToRoute('verify_failed');
    }
}

Webhook Verification

Verify incoming webhook signatures using HMAC-SHA256:

<?php

$event = $xident->webhooks()->constructEvent(
    payload:   file_get_contents('php://input'),
    signature: $_SERVER['HTTP_X_XIDENT_SIGNATURE'],
    secret:    $_ENV['XIDENT_WEBHOOK_SECRET'],
);

match ($event['type']) {
    'session.completed' => handleCompleted($event['data']),
    'session.failed'    => handleFailed($event['data']),
    default             => null,
};

Error Handling

<?php

use Xident\SDK\Exceptions\XidentException;
use Xident\SDK\Exceptions\AuthenticationException;
use Xident\SDK\Exceptions\NotFoundException;

try {
    $result = $xident->verification()->getResult($token);
} catch (AuthenticationException $e) {
    // 401 - Invalid API key
} catch (NotFoundException $e) {
    // 404 - Token not found
} catch (XidentException $e) {
    echo $e->getErrorCode();   // API error code
    echo $e->getRequestId();   // For support tickets
}

Using the REST API Directly

If you prefer not to use the SDK, you can call the Xident API directly with cURL:

<?php
// If you prefer not to use the SDK, call the API directly:

$token = filter_input(INPUT_GET, 'token', FILTER_SANITIZE_SPECIAL_CHARS);

$ch = curl_init('https://api.xident.io/verify/v1/result/' . urlencode($token));
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'X-API-Key: ' . $_ENV['XIDENT_SECRET_KEY'],
        'Accept: application/json',
    ],
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if ($response['success'] && $response['data']['status'] === 'completed') {
    // Verified
}

PHP 8.5+ note: curl_close() is deprecated as of PHP 8.5 and will be removed in a future version. cURL handles are automatically freed when they go out of scope. You can safely remove the curl_close($ch) call if you're targeting PHP 8.5+.

Configuration

OptionDefaultDescription
apiKey(required)Your secret API key (sk_live_* or sk_test_*)
baseUrlhttps://api.xident.ioAPI base URL
timeout30Request timeout in seconds
maxRetries3Max retries on 5xx errors

Related