querri / embed
PHP SDK for embedding Querri analytics into your application
Requires
- php: ^8.3
- ext-hash: *
- ext-json: *
- symfony/http-client: ^7.2
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
README
Embed Querri analytics in your PHP application. One method call, zero config.
Laravel | Symfony | Plain PHP | WordPress
PHP SDK for creating embed sessions, managing users, and controlling access policies via the Querri API. Use it with any PHP framework alongside the @querri-inc/embed frontend component. One getSession() call, one server endpoint, and you're done.
Get Started in 60 Seconds
1. Install
composer require querri/embed
2. Create a session
use Querri\Embed\QuerriClient; $client = new QuerriClient('qk_your_api_key'); $session = $client->getSession([ 'user' => 'customer-42', // external ID from your system 'ttl' => 3600, ]); echo $session->sessionToken; // JWT to pass to the frontend
3. Add the embed (React)
import { QuerriEmbed } from '@querri-inc/embed/react'; <QuerriEmbed style={{ width: '100%', height: '600px' }} serverUrl="https://app.querri.com" auth={{ sessionEndpoint: '/api/querri-session' }} />
4. Wire the endpoint
// public/api/querri-session.php (or your framework's route handler) $client = new QuerriClient(); // reads QUERRI_API_KEY from env $session = $client->getSession([ 'user' => ['external_id' => $authUser->id, 'email' => $authUser->email], 'ttl' => 3600, ]); header('Content-Type: application/json'); echo json_encode($session);
Set QUERRI_API_KEY and QUERRI_ORG_ID environment variables. In production, always derive user identity from your auth system — never from the request body.
5. Done.
The embed handles auth, token caching, and cleanup automatically.
sequenceDiagram
participant Browser
participant PHP Server
participant Querri API
Browser->>PHP Server: POST /api/querri-session
PHP Server->>Querri API: getOrCreate user + create session
Querri API-->>PHP Server: { session_token }
PHP Server-->>Browser: { session_token }
Browser->>Querri API: Load embed with token
Loading
Security: Always derive user identity and access from your server-side auth system. Never read
useroraccessfrom the request body — a malicious client can impersonate any user or escalate access.
Configuration
The SDK reads configuration from constructor arguments or environment variables:
| Parameter | Env Variable | Default | Description |
|---|---|---|---|
api_key |
QUERRI_API_KEY |
(required) | Your Querri API key (qk_...) |
org_id |
QUERRI_ORG_ID |
null |
Organization ID |
host |
QUERRI_URL |
https://app.querri.com |
Querri API host |
timeout |
— | 30.0 |
Request timeout in seconds |
max_retries |
— | 3 |
Max retries on 429/5xx errors |
// Read from environment variables $client = new QuerriClient(); // API key string shorthand $client = new QuerriClient('qk_...'); // Full config array $client = new QuerriClient([ 'api_key' => 'qk_...', 'org_id' => 'org_...', 'host' => 'https://app.querri.com', 'timeout' => 30.0, 'max_retries' => 3, ]);
getSession() — Embed Sessions
The flagship method that creates an embed session in three steps:
- User resolution — creates or retrieves a Querri user by your external ID
- Access policy — auto-creates or reuses a deterministic policy with row-level filters
- Session creation — generates a JWT token for the embed iframe
With inline access rules
$session = $client->getSession([ 'user' => [ 'external_id' => 'customer-42', 'email' => 'alice@acme.com', 'first_name' => 'Alice', ], 'access' => [ 'sources' => ['src_sales_data'], 'filters' => [ 'tenant_id' => 'acme', 'region' => ['us-east', 'us-west'], ], ], 'origin' => 'https://app.acme.com', 'ttl' => 7200, ]);
With pre-created policy IDs
$session = $client->getSession([ 'user' => ['external_id' => 'customer-42'], 'access' => ['policy_ids' => ['pol_abc123', 'pol_def456']], ]);
GetSessionResult
$session->sessionToken; // string — JWT for the embed $session->expiresIn; // int — seconds until expiry $session->userId; // string — Querri user ID $session->externalId; // string|null — your external ID // JSON-serializable for API responses echo json_encode($session); // {"session_token":"...","expires_in":3600,"user_id":"...","external_id":"..."}
Direct Resource Usage
For advanced use cases, access the API resources directly:
Users
$user = $client->users->getOrCreate('ext-123', [ 'email' => 'user@example.com', 'role' => 'member', ]); $user = $client->users->retrieve('usr_abc123'); $users = $client->users->list(['limit' => 50]); $client->users->update('usr_abc123', ['first_name' => 'Alice']); $client->users->del('usr_abc123');
Policies
$policy = $client->policies->create([ 'name' => 'APAC Sales', 'source_ids' => ['src_1'], 'row_filters' => [ ['column' => 'region', 'values' => ['APAC']], ], ]); $client->policies->assignUsers($policy['id'], ['usr_abc123']); $client->policies->removeUser($policy['id'], 'usr_abc123');
Embed Sessions
$session = $client->embed->createSession([ 'user_id' => 'usr_abc123', 'ttl' => 3600, ]); $refreshed = $client->embed->refreshSession($session['session_token']); $client->embed->revokeSession('ses_abc123'); $client->embed->revokeUserSessions('usr_abc123');
All Resources
Beyond the core embed resources above, the SDK provides full access to the Querri API:
| Resource | Access | Key Methods |
|---|---|---|
$client->dashboards |
Dashboard management | list, create, retrieve, update, del, refresh |
$client->projects |
Analysis projects | list, create, retrieve, run, runStatus |
$client->chats |
Chats within projects | create, list, retrieve, del, cancel |
$client->data |
Data sources & queries | listSources, createSource, query, appendRows |
$client->sources |
Connectors & sync | listConnectors, list, create, sync |
$client->files |
File management | list, retrieve, del |
$client->keys |
API key management | create, list, retrieve, revoke |
$client->audit |
Audit log | listEvents |
$client->usage |
Usage metrics | getOrgUsage, getUserUsage |
$client->sharing |
Sharing & permissions | shareProject, shareDashboard, shareSource |
See docs/server-sdk.md for complete method signatures and examples.
Error Handling
All errors extend QuerriException. API errors are mapped to specific exception types:
QuerriException
├── ConfigException — missing/invalid configuration
├── ConnectionException — network failures (auto-retried)
│ └── TimeoutException — request timeout exceeded
└── ApiException — HTTP error responses
├── ValidationException — 400
├── AuthenticationException — 401
├── PermissionException — 403
├── NotFoundException — 404
├── ConflictException — 409
├── RateLimitException — 429 (auto-retried)
└── ServerException — 5xx (auto-retried)
use Querri\Embed\Exceptions\ApiException; use Querri\Embed\Exceptions\AuthenticationException; use Querri\Embed\Exceptions\RateLimitException; use Querri\Embed\Exceptions\ConfigException; try { $session = $client->getSession([...]); } catch (AuthenticationException $e) { // 401 — invalid API key echo "Auth failed: {$e->getMessage()}"; } catch (RateLimitException $e) { // 429 — rate limited (auto-retried up to maxRetries) echo "Rate limited, retry after: {$e->retryAfter}s"; } catch (ApiException $e) { // Any other API error echo "API error {$e->status}: {$e->getMessage()}"; echo "Request ID: {$e->requestId}"; } catch (ConfigException $e) { // Missing API key or invalid config echo $e->getMessage(); }
The SDK automatically retries 429 (always) and 5xx (idempotent methods only) with exponential backoff + jitter, up to max_retries attempts.
Example App
See examples/react-embed/ for a complete working example with a PHP backend and React frontend.
Full Reference
See docs/server-sdk.md for the complete API reference, including every method signature, framework integration guides (Laravel, Symfony), error handling details, and the getSession() deep dive.
Troubleshooting
"API key is required" error
Set the QUERRI_API_KEY environment variable. Find your API key at app.querri.com/settings/api-keys.
# .env or your server config
QUERRI_API_KEY=qk_your_api_key
QUERRI_ORG_ID=org_your_org_id
The SDK checks getenv(), $_ENV, and $_SERVER — covering CLI, Apache, nginx+FPM, and Docker.
Embed is blank / session endpoint returns 500
Verify your PHP endpoint returns JSON with the correct Content-Type:
header('Content-Type: application/json'); echo json_encode($session); // GetSessionResult is JsonSerializable
CORS errors in development
Use Vite's dev proxy to forward /api requests to your PHP server — no CORS headers needed:
// vite.config.ts server: { proxy: { '/api': 'http://localhost:8080' } }
Class not found errors
Ensure Composer's autoloader is loaded before using SDK classes:
require_once __DIR__ . '/vendor/autoload.php';
Important Notes
- This SDK uses the Server Token auth mode. Your PHP backend creates session tokens and the frontend embed consumes them. For other auth modes (Share Key, Popup Login), see the JS SDK docs.
- React/Vue/Angular: Memoize the
authprop if it's an object. A new object reference on every render cycle causes the iframe to be destroyed and recreated. - The PHP SDK covers the full Querri API (all 13 resources). For frontend-only use cases, see the JS SDK.
Requirements
- PHP 8.3+
ext-jsonext-hashsymfony/http-client^7.2
License
MIT