Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Sdk Laravel Package

snappy/php-sdk

A lightweight PHP SDK for integrating the Snappy API into PHP and Laravel applications, offering simple authentication, request helpers, and framework-friendly configuration. A compact starting point for teams building Snappy-powered workflows without boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a thin PHP client for the Snappy (BeSnappy) customer-support platform API — not the wkhtmltopdf/PDF ecosystem. With 9 stars and zero dependents, treat it as a convenience wrapper over HTTP you happen to install, not a supported framework integration. Budget an hour to read the source before you write any product code against it.

Confirm the identity before you install. The repository is BeSnappy/php-sdk, but the package name in the assessment line is snappy/php-sdk and prior notes suggest besnappy/php-sdk. Read the composer.json in the repo and use the exact name field:

composer require <exact-vendor>/php-sdk:^0.1   # pin conservatively, never `*`

Verify in the same pass:

  • PHP constraint (an unmaintained package often caps below 8.2).
  • Whether it constrains guzzlehttp/guzzle or psr/http-client in a way that conflicts with the rest of your app.
  • Whether it ships a ServiceProvider and façade or expects manual wiring. Most SDKs this size do not.

Configure credentials in config/services.php, never inline.

// config/services.php
'snappy' => [
    'key' => env('SNAPPY_API_KEY'),
    'url' => env('SNAPPY_API_URL', 'https://api.besnappy.com'),
],

First place to look, in order:

  1. README.md — usage example, auth model (API key vs OAuth), supported endpoints.
  2. composer.json — real package name, PHP/Guzzle constraints, autoload namespace, require-dev.
  3. src/ — the client class, the auth/credential object, the request builder, the response wrapper, and the exception types. These four are what you will actually touch.
  4. tests/ — if present, the fastest source of truth on request shape and error behavior. If absent, that is a signal.

First use case — a smoke test, not a feature. In tinker, construct the client with sandbox credentials, create one ticket, read one contact, and dump the raw and parsed responses. Capture the exact JSON shapes into a one-page contract note. That note — not the SDK — becomes the artifact your team onboards from. Nothing else should be built until this passes.

$client = app(\App\Services\Snappy\SnappyClient::class); // your adapter, see below
$ticket = $client->createTicket([
    'subject' => 'Smoke test',
    'body'    => 'Created from the spike',
    'email'   => '[email protected]',
]);

Implementation Patterns

Wrap it behind an interface you own. This is the single highest-value pattern given the maturity signals. The SDK is transport; your domain should never see its classes.

// app/Services/Snappy/SnappyClient.php  (our contract)
interface SnappyClient
{
    public function createTicket(CreateTicketData $data): Ticket;
    public function findContact(string $email): ?Contact;
}

Bind the concrete implementation in a dedicated service provider, and inject the SDK's client into it — never resolve the SDK directly from controllers or jobs:

// app/Providers/SnappyServiceProvider.php
$this->app->singleton(SnappyClient::class, function ($app) {
    return new SdkSnappyClient(
        sdk: new \Snappy\Client(config('services.snappy')),
        // optionally inject a PSR-18 client here if the SDK accepts one
    );
});

The adapter maps SDK responses into your DTOs and translates SDK exceptions into your own exception hierarchy. That indirection costs roughly a day and buys you the ability to swap the SDK for a Saloon connector or raw Http calls without touching a single call site.

Do all writes in queued jobs. Never call Snappy synchronously inside a request a user is waiting on — you inherit the vendor's latency and availability. The SDK's default timeouts and retries are almost certainly not tuned for your SLOs.

class CreateSupportTicket implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public int $backoff = 30;

    public function handle(SnappyClient $snappy): void
    {
        $snappy->createTicket($this->data);
    }

    public function failed(\Throwable $e): void
    {
        // dead-letter, alert, or queue for manual review
    }
}

Roll out behind a config flag, write paths first. Ship createTicket or contact-sync-on-signup behind services.snappy.enabled. No reads in user-facing request paths for the first release cycle. Add read paths, then webhooks, once the write path has run clean.

Webhooks are your problem, not the SDK's. Assume no signature verification helper. Build a dedicated endpoint that verifies the HMAC against the raw request body, returns 200 immediately, and dispatches a job:

Route::post('/webhooks/snappy', SnappyWebhookController::class)
    ->withoutMiddleware(['csrf']);

Verify against $request->getContent() (raw body), not $request->all(), or the signature will never match.

Test against your adapter, not the SDK. Because everything funnels through SnappyClient, you can fake it in feature tests and reserve Http::fake() for the adapter's own unit tests — which is where you assert request shape, auth headers, and error mapping.

$this->mock(SnappyClient::class)
    ->shouldReceive('createTicket')
    ->once()
    ->andReturn(new Ticket(id: '123', ...));

Rate limiting and retries live outside the SDK. Implement a per-tenant throttle (Laravel's RateLimiter or a token bucket) and retry-on-429 with jitter in the adapter or the job — thin SDKs typically inherit raw Guzzle defaults, which means no backoff, no jitter, and no awareness of Retry-After.

Gotchas and Tips

Name collision is the first trap. knplabs/knp-snappy and barryvdh/laravel-snappy are wkhtmltopdf PDF wrappers with thousands of dependents. They are unrelated. If a search, a Stack Overflow answer, or an existing dependency in your app references "Snappy" for PDF generation, that is not this. Search for the exact vendor name, not "snappy".

Expect no Laravel integration. No service provider, no façade, no config publishing, no Http::fake()-aware transport. You will create the service provider and config file yourself, as shown above. If the README implies otherwise, check that the code actually matches.

Test whether the HTTP client is injectable. If the SDK accepts a PSR-18 client / PSR-17 factory in its constructor, inject a Guzzle instance configured with your app's logging middleware and timeout — that gives you observability and tracing for free, and makes Http::fake() style testing feasible. If it hardcodes new GuzzleHttp\Client(), you cannot instrument it without reflection hacks; that downgrades the package's value and strengthens the case for a 200-line Saloon connector instead.

Watch the transitive dependency graph on the first composer update. An older Guzzle pin than the rest of the app is a stop-ship item, not something to work around later. Same for any illuminate/* constraints. Resolve this before writing product code.

Error taxonomy will likely under-deliver. Verify explicitly: does the SDK throw typed exceptions for 401/404/422/429, or does it throw a generic HTTP exception with the body attached? Plan to parse status and the error payload in the adapter and translate into your own SnappyAuthenticationException, SnappyValidationException, etc. Your jobs and alerting depend on that distinction — a 401 (rotate secret, alert) and a 429 (retry) must not look the same.

Pagination semantics are the second common gap. Confirm whether the SDK exposes cursors/links, returns a single page, or lazy-iterates. If it only returns a page, write the loop in the adapter and cap it, or you will silently truncate contact syncs.

Idempotency is on you. If the SDK does not accept idempotency keys on create, a retried job after a timeout will produce duplicate tickets. Mitigate on your side: record a dedupe key (e.g. your internal ticket-intent UUID) before dispatch and check on retry, or query-then-create in the adapter.

Pin the version exactly-ish and review the changelog on every bump. For an unmaintained package, a minor release can silently change a field mapping with no exception thrown. composer.json constraint plus committed lockfile plus a changelog read is the whole safety net. Track the package in your dependency dashboard with an explicit "unmaintained → replace" trigger; an abandoned SDK should degrade into a fork-or-replace decision, not an outage.

Log requests and responses at the adapter boundary (redacting auth headers) from day one. With no community corpus and sparse docs, your own logs will be the primary debugging tool for the first few months. Alert on 401 rate specifically — auth/secret expiry is the failure mode that takes the whole integration down silently.

Config caching: always php artisan config:clear after touching config/services.php. A cached config with a stale key produces a 401 that looks like bad credentials and costs an hour.

Keep the adapter's interface as the onboarding artifact. With low organizational ramp-up risk, the knowledge will otherwise concentrate in whoever did the spike. Document the contract note from the smoke test alongside the interface, and point support questions at your seam — not at SDK internals, which may never be updated.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo