PHP SDK
The PHP SDK is a typed client over the V2 API. One Client, a resource per API area, and an Eloquent-flavoured query builder for analytics. Laravel apps get a facade and session-id plumbing on top; see Laravel.
composer require snipform/php-sdkRequires PHP 8.2+, Guzzle 7, and symfony/http-foundation 6 or 7. The Laravel layer is optional and activates when illuminate/support (10 to 13) is installed.
Create a client
Section titled “Create a client”use SnipForm\SnipForm;
$snipform = SnipForm::client('YOUR_PROPERTY_TOKEN');
$metrics = $snipform->signals()->last7Days()->metrics();
echo "Sessions: {$metrics->sessions}, bounce: {$metrics->bounceRate}%";The token is a property-scoped API token created in the dashboard under Property → API. Everything the client does is scoped to that property, and the token’s scopes decide which calls succeed. See Authentication & Tokens.
SnipForm::client($token, $options) is shorthand for new SnipForm\Client($token, $options). Options:
| Option | Default | Notes |
|---|---|---|
base_url | https://api.snipform.io | |
path_prefix | /v2/ | Older self-hosted deployments may serve under /api/v2/ |
timeout | 30 | Seconds per request |
verify_ssl | true | Set false only for local self-signed certificates |
Every request carries User-Agent: snipform-php-sdk/0.0.13.
Resources
Section titled “Resources”Each $snipform->resource() call returns a fresh instance, so chains never leak state into one another.
| Call | Covers | Reference |
|---|---|---|
signals() | Sessions, metrics, graph, live | Querying Signals |
session() | Event and acquisition writes on one session | Resources |
contacts() | Identify, list, update, delete contacts | Resources |
conversions() | Definitions and funnel analytics | Resources |
linkGroups(), links(), clicks() | Short links | Resources |
attribution() | Channel preview and UTM presets | Resources |
properties() | Property overview | Below |
Property overview
Section titled “Property overview”$property = $snipform->properties()->overview();
$property->id; // string$property->name; // string$property->domain; // string$property->hasSignals; // bool - tracking has fired at least once$property->state; // string|null$property->stateName; // string|null - human label$property->counts; // ['sessions' => 188862, 'forms' => 4, 'pages' => 2, ...]Data objects
Section titled “Data objects”Every typed return value extends SnipForm\Data\SnipFormDTO: public readonly properties, toArray(), and JsonSerializable.
$metrics->toArray(); // associative array of the public fieldsjson_encode($metrics); // same thingDTOs carry only the fields the SDK surfaces. When you need something else from the response, switch the chain to raw mode:
$snipform->properties()->asRaw()->overview(); // array$snipform->signals()->last28Days()->asRaw()->metrics(); // array with analytics, meta, options$snipform->conversions()->asRaw()->find($id); // arrayasRaw() works on every resource and is forwarded into builders started from it (conversions()->asRaw()->create()->...->save() returns an array). The raw array is the data block of the API envelope.
Pagination
Section titled “Pagination”List endpoints return a PaginatedCollection. Iterating walks every page; the other helpers fetch what they need and no more.
$sessions = $snipform->signals()->last28Days()->sessions();
foreach ($sessions as $session) { ... } // page after page, transparently$sessions->first(); // first row, one request$sessions->count(); // total from the paginator meta$sessions->all(); // every row in memory - be careful->page($n) fetches one page and returns a SnipForm\Data\Page with the rows plus the paginator meta:
$page = $snipform->signals()->sessions(20)->page(2);
$page->items; // SessionRow[] (arrays in raw mode)$page->currentPage; // 2$page->lastPage; // 5$page->total; // 230$page->perPage; // 20$page->from; // 21$page->to; // 40$page->hasMore(); // bool$page->isFirstPage();$page->isLastPage();
$page->next(); // Page 3, or null on the last page - one request$page->prev(); // Page 1, or null on the first page$page->first();$page->last();$page->pageLink($page->nextPageUrl); // follow any paginator URL$page->raw(); // the full paginator JSON, including `links`A Page is iterable, countable and array-accessible, so foreach ($page as $row), count($page) (rows on this page) and $page[0] all work.
Returning from a controller
Section titled “Returning from a controller”DTOs, PaginatedCollection and Page are all JsonSerializable, so a Laravel or PSR-7 controller can return them as-is:
public function dashboard(\SnipForm\Client $snipform){ return $snipform->signals()->last7Days()->metrics(); // typed JSON}
public function sessions(\SnipForm\Client $snipform, Request $request){ return $snipform->signals() ->last28Days() ->sessions(20) ->page((int) $request->input('page', 1)); // Laravel paginator JSON}A PaginatedCollection serialises as page 1 in Laravel’s paginator shape (data, current_page, last_page, total, next_page_url, …). Return a Page for a specific page.
Errors
Section titled “Errors”Everything the SDK throws extends SnipForm\Exceptions\SnipFormException.
| Exception | When | Before HTTP? |
|---|---|---|
InvalidPeriodException | A string passed to period() is not a known period | Yes |
IncompatibleFieldOperator | A SessionField case used with an operator its type does not support | Yes |
MissingSessionIdException | session()->event() or acquisition() could not resolve a session id | Yes |
AuthenticationException | 401 or 403: bad token, wrong property, missing scope | No |
ApiException | Any other 4xx or 5xx with a structured body | No |
SnipFormException | Transport failure, JSON decode failure, anything else | No |
use SnipForm\Exceptions\ApiException;use SnipForm\Exceptions\AuthenticationException;use SnipForm\Exceptions\SnipFormException;
try { $rows = $snipform->signals()->last7Days()->sessions()->all();} catch (AuthenticationException $e) { // token revoked, expired, or missing signals:read} catch (ApiException $e) { $e->status; // int - HTTP status $e->errors; // ['field' => ['message', ...]] for 422s, otherwise [] $e->body; // the full response body} catch (SnipFormException $e) { // network, timeout, malformed response}Validation errors are folded into the message, so a 422 reads as The given data was invalid. period: must be one of ... in the stack trace without unpacking $e->errors.
- Querying Signals: periods, clauses, sessions, metrics, graph and live.
- Resources: events, contacts, conversions, short links, attribution.
- Laravel: the facade, session-id delivery, dispatch modes, auto-identify.