PHP code example of kinetistack-io / php-sdk

1. Go to this page and download the library: Download kinetistack-io/php-sdk library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

kinetistack-io / php-sdk example snippets


use KinetiStack\Sdk\KinetiClient;

// Basic initialization
$client = new KinetiClient(
    'https://api.kinetistack.io', // Your API host
    'sk_test_12345'               // Your project API key
);

// Advanced initialization with custom options and automatic retries
$client = new KinetiClient(
    apiHost: 'https://api.kinetistack.io',
    apiKey: 'sk_test_12345',
    httpClient: null,             // Optional: PSR-18 ClientInterface (e.g. Guzzle), Symfony HttpClientInterface, or auto-discovered
    options: [
        'timeout' => 30.0,        // Request timeout in seconds
        'max_retries' => 3,       // Automatically retry transient HTTP 429 and 503 errors
    ]
);

// From a URL
$response = $client->analyzeImage('https://example.com/image.jpg', [
    'page_title' => 'Renewable Energy'
]);
echo $response->altText;
if ($response->tokensConsumed !== null) {
    echo "Tokens consumed: {$response->tokensConsumed}\n";
}

// From a stream resource (memory-efficient for large files & remote stream wrappers)
$stream = fopen('/path/to/image.jpg', 'rb');
$response = $client->analyzeImageStream($stream, 'image.jpg');
fclose($stream);

// From a local file (uses streams internally)
$response = $client->analyzeImageBinary('/path/to/image.jpg');

// From binary string content
$response = $client->analyzeImageContent($binaryData, 'image.jpg');

use KinetiStack\Sdk\Dto\ImageInputDto;
use KinetiStack\Sdk\Dto\JobDto;
use KinetiStack\Sdk\Exception\JobTimeoutException;
use KinetiStack\Sdk\KinetiClient;

// Submit a batch of images (URL or Base64 / Data URI)
$batch = $client->submitBatchJob([
    new ImageInputDto('media:1', 'https://example.com/1.jpg'),
    new ImageInputDto('media:2', imageBase64: 'data:image/jpeg;base64,...'),
]);

echo $batch->jobId; // E.g., '123e4567-e89b-12d3-a456-426614174000'

// Poll for completion with exponential backoff & jitter
try {
    $completedBatch = $client->waitForJob(
        jobId: $batch->jobId,
        timeoutSeconds: KinetiClient::DEFAULT_TIMEOUT_SECONDS,                  // Default: 60s
        pollIntervalSeconds: KinetiClient::DEFAULT_POLL_INTERVAL_SECONDS,         // Default: 2s (initial interval)
        onProgress: function (JobDto $job): void {
            echo "Current status: {$job->status->value}\n";
        },
        maxPollIntervalSeconds: KinetiClient::DEFAULT_MAX_POLL_INTERVAL_SECONDS // Default: 10s (capped interval)
    );
    
    if ($completedBatch->tokensConsumed !== null) {
        echo "Tokens consumed: {$completedBatch->tokensConsumed}\n";
    }

    foreach ($completedBatch->results as $result) {
        echo $result->externalId . ': ' . $result->altText . "\n";
    }
} catch (JobTimeoutException $e) {
    echo "Job timed out. Last known status: " . $e->latestJob->status->value;
}

use KinetiStack\Sdk\Dto\RagStreamChunkDto;
use KinetiStack\Sdk\Dto\SearchQueryDto;

// 1. Standard search with optional synthesized answer
$query = SearchQueryDto::create('How does solar net metering work?')
    ->withLimit(5)
    ->withSynthesis(true);

$response = $client->search($query);
echo "Found {$response->total} results.\n";
if ($response->tokensConsumed !== null) {
    echo "Tokens consumed: {$response->tokensConsumed}\n";
}
if ($response->hasSynthesis()) {
    echo "Synthesized Answer: " . $response->synthesis->answer . "\n";
    if ($response->synthesis->tokensConsumed !== null) {
        echo "Synthesis Tokens: " . $response->synthesis->tokensConsumed . "\n";
    }
}

// 2. Streamed RAG synthesis via PHP generator (reduces perceived latency)
$streamQuery = SearchQueryDto::create('Explain commercial solar financing options')
    ->withLimit(5)
    ->withStream(true);

/** @var \Generator<int, RagStreamChunkDto> $stream */
$stream = $client->searchStream($streamQuery);

foreach ($stream as $chunk) {
    echo $chunk->text; // Streams partial tokens/words in real-time
    if ($chunk->tokensConsumed !== null) {
        echo "\nTokens consumed: {$chunk->tokensConsumed}\n";
    }
    flush();
}

use KinetiStack\Sdk\WebhookVerifier;

$payload = file_get_contents('php://input');
$signatureHeader = $_SERVER['HTTP_X_KINETI_SIGNATURE'] ?? '';
$webhookSecret = 'whsec_your_secret_key';

$isValid = WebhookVerifier::verify($payload, $signatureHeader, $webhookSecret);

if (!$isValid) {
    http_response_code(401);
    exit('Invalid signature');
}

use KinetiStack\Sdk\Exception\AuthenticationException;
use KinetiStack\Sdk\Exception\AuthorizationException;
use KinetiStack\Sdk\Exception\KinetiException;
use KinetiStack\Sdk\Exception\NotFoundException;
use KinetiStack\Sdk\Exception\PayloadTooLargeException;
use KinetiStack\Sdk\Exception\RateLimitException;
use KinetiStack\Sdk\Exception\ServerException;
use KinetiStack\Sdk\Exception\ServiceUnavailableException;
use KinetiStack\Sdk\Exception\ValidationException;

try {
    $client->analyzeImage('invalid-url');
} catch (ValidationException $e) {
    print_r($e->violations);
} catch (RateLimitException $e) {
    // Thrown if max_retries is not configured or all retry attempts are exhausted
    echo "Rate limited. Retry after: " . $e->retryAfter . " seconds.";
} catch (ServiceUnavailableException $e) {
    // Thrown if max_retries is not configured or all retry attempts are exhausted
    echo "Service temporarily unavailable (503): " . $e->getMessage();
} catch (KinetiException $e) {
    echo "API Error: " . $e->getMessage();
}

use KinetiStack\Sdk\AdminClient;

// 1. Initial login without token
$admin = new AdminClient('https://api.kinetistack.io');
$auth = $admin->login('[email protected]', 'SuperSecret123!');

// 2. Obtain an immutable client instance with the JWT token
$authenticatedAdmin = $admin->withToken($auth->token);

// Or initialize directly if you already hold a valid token
$admin = new AdminClient('https://api.kinetistack.io', $jwtToken);

// Organizations are initialized during registration (POST /api/v1/admin/register).
// Once registered, manage your organization via item operations:
$orgId = 'org-uuid-123'; // Obtained from registration response or user profile
$currentOrg = $admin->getOrganization($orgId);
$updatedOrg = $admin->updateOrganization($orgId, ['name' => 'Acme Global Agency']);

// Projects
$project = $admin->createProject('Client Portal', 'portal.example.com', 'https://webhook.example.com/events');
$projects = $admin->listProjects();
$projectDetails = $admin->getProject($project->id);
$admin->updateProject($project->id, ['settings' => ['theme' => 'dark']]);
$admin->deleteProject($project->id); // Soft-delete and revokes associated API keys

// Create API key (returns ApiKeyCreatedDto with plaintext token)
$newKey = $admin->createApiKey($project->id, 'Production Drupal Key', 'all', rateLimitPerMinute: 120);
echo $newKey->token; // Secret plaintext token — save this now!
echo $newKey->tokenSuffix; // e.g. '1234'

// List API keys (returns ApiKeyDto[] without plaintext token, with optional usage metrics)
$keys = $admin->listApiKeys($project->id);
foreach ($keys as $key) {
    $tokens = $key->tokensConsumedToday ?? 0;
    $requests = $key->requestsToday ?? 0;
    echo "{$key->name}: {$tokens} tokens consumed today across {$requests} requests\n";
}

// Rotate API key (old key continues working during grace period)
$rotated = $admin->rotateApiKey($project->id, $newKey->id);
echo $rotated->token; // New secret token

// Revoke API key
$admin->revokeApiKey($project->id, $newKey->id);

use KinetiStack\Sdk\AnalyticsClient;
use KinetiStack\Sdk\Enum\AnalyticsGrouping;

// Summary report across services (supports optional apiKeyId filter)
$usage = $admin->getUsage(from: '2026-09-01', to: '2026-09-05', projectId: $project->id, apiKeyId: $newKey->id);
foreach ($usage as $summary) {
    echo "{$summary->projectName} - {$summary->service}: {$summary->totalTokens} tokens ({$summary->requestCount} requests)\n";
}

// Time-bucketed analytics with typed grouping (DAY, WEEK, MONTH) via AdminClient
$dailyAnalytics = $admin->getAnalytics(grouping: AnalyticsGrouping::DAY, from: '2026-09-01', to: '2026-09-07');
$weeklyAnalytics = $admin->getAnalytics(grouping: AnalyticsGrouping::WEEK, from: '2026-09-01', to: '2026-09-30');
$monthlyAnalytics = $admin->getAnalytics(grouping: AnalyticsGrouping::MONTH);
print_r($weeklyAnalytics->data);

// Or via dedicated AnalyticsClient
$analyticsClient = $admin->analytics();
// Or standalone: new AnalyticsClient('https://api.kinetistack.io', $jwtToken)
$trends = $analyticsClient->getAnalytics(AnalyticsGrouping::WEEK);