viewmend / sdk
Official framework-agnostic PHP SDK for ViewMend APIs, including Site Tracker events and Cron.
Requires
- php: >=8.3
- guzzlehttp/guzzle: ^7.9
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1 || ^2.0
- psr/log: ^3.0
Requires (Dev)
- nyholm/psr7: ^1.8
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5 || ^12.0
- squizlabs/php_codesniffer: ^3.13
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
The ViewMend PHP SDK is the official framework-agnostic PHP client for ViewMend APIs. It provides shared authentication and configuration, a production-ready HTTP transport, safe retries, typed errors, and isolated product modules for integrating PHP applications with the ViewMend website monitoring platform.
Available modules
Site Tracker
PHP applications can send deployment events, content updates, cache clears, and maintenance activity to ViewMend, which connects that change context with subsequent checks of tracked pages in the Events and Timeline workflow.
Applications can also read integration dashboards and paginated check resources using the same Site Tracker token.
Learn more about ViewMend Site Tracker for website change monitoring.
Cron
Applications can register one scheduled HTTPS callback for the domain connected in ViewMend. The client chooses the schedule and callback path; ViewMend fixes the method to POST, verifies the endpoint, and runs it on a dedicated queue. The client never submits an arbitrary callback host.
Installation
Install the SDK with Composer:
composer require viewmend/sdk
Guzzle is included as the SDK's default HTTP transport; application code does not need to install, configure, or import it.
Quick Start
This example uses Site Tracker Events:
<?php declare(strict_types=1); use ViewMend\ViewMend; require __DIR__ . '/vendor/autoload.php'; $token = getenv('VIEWMEND_API_TOKEN'); if ($token === false || trim($token) === '') { throw new \RuntimeException('VIEWMEND_API_TOKEN is required.'); } $token = trim($token); $integrationId = getenv('VIEWMEND_INTEGRATION_ID'); if ($integrationId === false || trim($integrationId) === '') { throw new \RuntimeException('VIEWMEND_INTEGRATION_ID is required.'); } $integrationId = trim($integrationId); $viewmend = ViewMend::client(token: $token); $result = $viewmend ->siteTracker($integrationId) ->events() ->deployment( id: 'deploy-abc123', title: 'Homepage deployed', ) ->send();
The default versioned API base URL is https://viewmend.com/api/v1. Creating and enriching an event performs no network request; the side effect occurs only when send() is called.
Add change context
Fluent methods add validated context while keeping the event immutable:
$result = $viewmend ->siteTracker($integrationId) ->events() ->deployment( id: 'deploy-abc123', title: 'Homepage deployed', ) ->site('https://example.com') ->page('https://example.com/') ->page('https://example.com/pricing') ->environment('production') ->description('Published release abc123.') ->reference('https://github.com/example/project/actions/runs/123') ->send();
site() identifies the affected site, while each page() adds a specific tracked-page URL. Supported semantic event methods are deployment(), contentUpdate(), pluginUpdate(), themeUpdate(), cacheCleared(), trackingScriptChange(), maintenance(), and custom().
For optional integration-declared changed_fields and metadata, see Site Tracker event context.
Use an event ID that is unique and stable for the originating change. Safe retries send the identical serialized payload and the same event ID. If the server already accepted that ID, it returns a duplicate delivery instead of creating a second event.
Read the Site Tracker dashboard
$tracker = $viewmend->siteTracker($integrationId); $dashboard = $tracker->dashboard(device: 'desktop'); $healthScore = $dashboard->summary->healthScore; // null until data is available $attentionItems = $dashboard->needsAttention->items; if ($dashboard->latestCheck !== null) { $resources = $tracker->resources( runId: $dashboard->latestCheck->runId, type: 'images', device: $dashboard->scope->device, perPage: 50, ); foreach ($resources->items as $resource) { // Use $resource->url, $resource->transferredBytes, and $resource->durationMs. } }
dashboard() and resources() perform GET requests and return immutable typed responses. See Site Tracker dashboards and resources for page selection, pagination, missing data, and error handling.
Register Cron
First create a connection for the site's domain in ViewMend and copy the one-time connection token into the application settings. The application then registers its callback path and schedule:
use ViewMend\ViewMend; $viewmend = ViewMend::client(token: $token); $cron = $viewmend->cron(); $registration = $cron->register( cron: '*/15 * * * *', timezone: 'Europe/London', endpointPath: '/cron', );
The registration request sends only an endpoint path. ViewMend combines that path with the connected domain and always calls it using HTTPS POST. The returned RegistrationResult contains the saved settings and current server state, so the application can update its form immediately. Registering a new or changed path starts endpoint verification before normal runs begin.
Load saved Cron settings
When the application settings screen opens, use the saved token to load the authoritative settings from ViewMend:
use ViewMend\Exception\AuthenticationException; use ViewMend\Exception\EndpointDisabledException; use ViewMend\Exception\NetworkException; use ViewMend\Exception\ServerException; use ViewMend\Exception\TokenScopeException; use ViewMend\ViewMend; $cron = ViewMend::client(token: $token)->cron(); try { $settings = $cron->current(); if ($settings === null) { // No schedule has been registered. Show the initial settings form. } else { $cronExpression = $settings->cron; $timezone = $settings->timezone; $enabled = $settings->enabled; // Display server state such as $settings->status and $settings->nextRunAt read-only. } } catch (TokenScopeException) { // A Site Tracker token was pasted into the Cron settings. } catch (AuthenticationException) { // The Cron connection token is invalid or has been rotated. } catch (EndpointDisabledException) { // The ViewMend connection is disabled. } catch (NetworkException|ServerException) { // ViewMend is temporarily unavailable. Show a clearly marked cached snapshot if one exists. }
current() calls GET /api/v1/cron/registration and returns null only when no registration exists. ViewMend is the source of truth. A client may keep the last successful response for temporary offline display, but it must not let that cache overwrite a later server response, and it must never cache or log the connection token as part of the settings snapshot. Catch TokenScopeException before AuthenticationException because it is the more specific authentication failure.
disable() pauses the saved schedule. See the complete settings synchronization contract.
The callback must verify the signature against the exact raw request body before processing it:
$callback = $cron->verifyCallback($requestHeaders, $rawRequestBody); if ($callback->isVerification()) { $responseBody = $callback->verificationResponseBody(); // Return $responseBody as application/json with a 2xx status. } else { // Deduplicate by $callback->runId, then run the scheduled task. // Return any 2xx response when processing succeeds. }
Cron delivery is at least once: a transient failure can cause the same runId to be delivered again with a higher attempt. Store completed run IDs before repeating side effects. See the complete Cron integration contract.
Handle the result
send() returns a typed DeliveryResult:
printf( "Delivery %s: event %s is %s (%s)\n", $result->deliveryId->value, $result->eventId->value, $result->duplicate ? 'a duplicate' : 'accepted', $result->queueStatus->value, );
QueueStatus preserves unknown future values. Use isKnown() for display decisions, but retain its raw value rather than treating a new server status as a malformed response.
All SDK failures extend ViewMend\Exception\ViewMendException. Significant API statuses have dedicated exception types:
TokenScopeExceptionwhen a Site Tracker token is passed to the Cron APIAuthenticationExceptionfor other 401 responsesEndpointDisabledExceptionfor 410PayloadTooLargeExceptionfor 413UnprocessableEventExceptionfor 422ResourceNotFoundExceptionfor dashboard/resource 404 responses, including an out-of-scope page or runUnprocessableQueryExceptionfor dashboard/resource 422 responsesUnprocessableRegistrationExceptionfor invalid Cron registrationCallbackVerificationExceptionfor an invalid or stale Cron callbackRateLimitExceptionfor exhausted 429 responsesServerExceptionfor exhausted 5xx responsesNetworkExceptionfor exhausted PSR-18 network failuresTransportExceptionfor other non-retryable transport failuresUnexpectedResponseExceptionfor unexpected status codes or malformed successful JSON
Exception messages and SDK log context do not include authorization headers, API tokens, or raw response bodies.
Advanced configuration
The SDK uses Guzzle by default. Applications that manage their own HTTP infrastructure can inject a PSR-18 client and PSR-17 factories. See Advanced configuration.
License
The ViewMend PHP SDK is available under the MIT License.
Development
composer validate --no-check-publish
composer test
composer analyse
composer cs:check
composer quality
Tests use mock PSR-18 clients and never send real network traffic or perform real sleeps. Architectural decisions and public boundaries are recorded in docs/architecture.md.