Download the PHP package pliic/pliic-php without Composer
On this page you can find all versions of the php package pliic/pliic-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download pliic/pliic-php
More information about pliic/pliic-php
Files in pliic/pliic-php
Package pliic-php
Short Description Official PHP SDK for the Pliic feedback and support platform: typed API client, end-user token minting, and webhook signature verification.
License MIT
Homepage https://pliic.com
Informations about the package pliic-php
pliic/pliic-php
Official PHP SDK for the Pliic feedback and support platform.
Use it to integrate Pliic natively into your backend instead of embedding the widget: create suggestions and tickets on behalf of your users, let them vote and comment from your own UI, mint widget SSO tokens, and verify webhook signatures.
Install
Requires PHP 8.2+ with ext-curl and ext-json. No other dependencies.
Quickstart
The secret key must stay server-side. Never ship it to a browser or mobile app.
Suggestions
Passing user_id (your external id) or user_email on reads adds user_has_voted to each suggestion, so you can render a native board with vote state.
Tickets
Passing user_id/user_email to tickets->get() scopes the lookup to that author instead of trusting the caller to check data.author themselves — no need to paginate tickets->list() first just to confirm ownership.
Surveys, analytics, privacy
Widget SSO tokens
If you also embed the widget, mint the end-user token server-side:
Hand $token to your frontend as the widget's userToken.
Webhooks
Verify the X-Pliic-Signature header (t=<unix>,v1=<hmac>) before trusting a payload:
Signatures older than 5 minutes are rejected by default (toleranceSeconds). Use $event->id as an idempotency key if you process events asynchronously: redeliveries of the same event carry the same id.
Errors
API failures throw typed exceptions, all extending Pliic\Exceptions\ApiErrorException:
| Status | Exception |
|---|---|
| 401 | AuthenticationException |
403 + error: insufficient_scope |
InsufficientScopeException (extends PermissionException) |
| 403 | PermissionException (plan feature not available, and any other refusal) |
| 404 | NotFoundException |
| 422 | ValidationException ($e->errors() has the field errors) |
| 429 | RateLimitException |
Mapping is driven by the API's stable error code, never by the message text, so wording changes never break your catch blocks. Network-level failures throw Pliic\Exceptions\TransportException.
Missing scope (the usual first-write surprise)
A newly created Pliic key is read-only. It carries suggestions:read and tickets:read and nothing else, so your first create() fails until someone enables the write scope — this is not a bug in your payload.
InsufficientScopeException tells you exactly what is missing and where to fix it:
It extends PermissionException, so existing catch (PermissionException) code keeps catching it — narrow to InsufficientScopeException only where you want to tell "wrong key permissions" apart from "plan does not include this".
Enable the scope in Pliic under Settings → API Keys → Scopes for the app the key belongs to.
Testing your integration
The HTTP transport is injectable, so you can fake it. Pliic\Testing\FakeHttpClient ships with the package and answers every endpoint with a realistic payload out of the box — no setup needed for the common case:
Seed a specific payload when a test cares about particular data:
ownedByEmail()/ownedByUserId() mirror the API's ownership scoping (a ticket read for a different user_email/user_id 404s). Note that once either is set, the fake denies every request that doesn't carry that exact query param — including one that, against the real API, wouldn't have been scoped at all: the real endpoints only enforce ownership when user_id/user_email is actually sent, so an unscoped read (neither param given) always succeeds there but 404s here. Reset new FakeHttpClient() between scenarios that need both behaviours in the same test.
failNextWithTransportError() simulates a network failure on the next call only. Assert on what was sent:
$fake->requests holds every call made (method, url, headers, body), and Pliic\Testing\Fixtures exposes every canned payload directly (Fixtures::suggestion(), Fixtures::ticket(), …) if you need one outside the fake — e.g. to assert against in a controller test. These fixtures are checked against the real API's OpenAPI spec in CI, so they don't drift silently.
Laravel
The bridge is optional and auto-discovered — it only loads when the host app is a Laravel application. It never adds illuminate/support to the SDK's own require, so plain-PHP consumers are unaffected.
1. Install (already done if you followed Install above):
2. Publish the config and set your environment variables:
Pliic\PliicClient is now bound as a singleton — resolve it anywhere via the container:
3. Register the webhook route and listen for the event:
The route verifies X-Pliic-Signature for you and dispatches Pliic\Laravel\Events\WebhookReceived — your app never touches the raw payload or the signature check.
Pliic retries failed deliveries with backoff, so the same event->id can arrive more than once. Dedupe by event->id (a cache entry or a unique constraint) before acting on it if the handler isn't naturally idempotent.
CSRF
The webhook route authenticates itself via X-Pliic-Signature, not a session, so it must run outside the web middleware group's CSRF check. Either:
- register it in
routes/api.php(no CSRF there by default), or - keep it in
routes/web.phpand add its URI toVerifyCsrfToken::$except:
The author vs sender fields (avoiding self-notifications)
Every webhook payload's data carries both an author (who the record belongs to — e.g. the suggestion's or ticket's original creator) and a sender (who actually triggered this event — could be the same person, a teammate, or nobody in particular). Compare their external_id before notifying anyone, so a user doesn't get pinged for their own comment or their own status change:
sender['type'] is 'member' when a teammate acted on your dashboard (its external_id is always null — members aren't app users), and 'app_user' when the end user themselves triggered the event.
Versioning
Semantic versioning. Development happens in the private Pliic monorepo; 4nuunes/pliic-php is the read-only distribution mirror. Report issues there — pull requests to the mirror cannot be merged.
Full guide: docs.pliic.com/integrations/sdk-php.
All versions of pliic-php with dependencies
ext-curl Version *
ext-json Version *