Search by

logipro / snp-php-client

fredlogipro

PHP client for the SocialNetworksPublisher (SNP) external API

v0.3.0 2026-10-17 21:47 UTC

This package is auto-updated.

Last update: 2026-10-17 21:55:13 UTC


README

PHP client for the SocialNetworksPublisher (SNP) external API (/api/v1).

Install

composer require logipro/snp-php-client

Installable from Packagist.

Requires PHP 7.4+ and a PSR-18 HTTP client plus PSR-17 factories (for example guzzlehttp/guzzle, or symfony/http-client with nyholm/psr7).

Quick start

use Logipro\Snp\Client\ClientOptions;
use Logipro\Snp\Client\Dto\PostCreateRequest;
use Logipro\Snp\Client\Dto\Schedule;
use Logipro\Snp\Client\SnpClient;

$client = SnpClient::create(
    'snp_live_xxx',
    'https://snp.logipro.fr/api/v1',
    ClientOptions::create()->withAcceptLanguage('fr-FR')
);

$brands = $client->brands()->list();
$channels = $client->channels()->listForBrand($brandId);

$result = $client->posts()->create(
    $brandId,
    PostCreateRequest::withSchedule(Schedule::now())->withText('Hello SNP'),
    20 // Prefer: wait=20 — returns 200 when publication finishes within the window
);
$post = $result->getPost();

Resources

AccessorOperations
brands()list(), get(), getApprovalPolicy(), updateApprovalPolicy(), getErrorDashboard(), listAuditLogs()
channels()listForBrand() (view=connected_only), listCatalogForBrand(), connect(), getConnection()
integration()createWebappHandoffCode() (scope integration:webapp-handoff)
posts()CRUD, retry(), approvals, duplicate(), bulk(), CSV importPreview* / importCommit(), recurrence helpers
media()listForBrand(), get(), delete(), listUsages(), uploads (uploadFromPath(), upload(), fromUrl())
webhooks()endpoint CRUD, listDeliveries(), getDelivery(), listDeliveryAttempts(), retryDelivery()
writingAids()getWritingSettings(), buildUtmUrl(), shortenLink(), listSavedTexts(), listHashtagGroups()

SnpClient::checkHealth($baseUrl) calls GET /health without sending an API key. Successful API responses expose rate-limit headers via $response->getRateLimit() (see RateLimitSnapshot).

create() and connect() send an Idempotency-Key header automatically (override per call). Pass waitSeconds (1–30) to create() or retry() to set Prefer: wait=….

Configuration

use Logipro\Snp\Client\ClientOptions;

$options = ClientOptions::create()
    ->withAcceptLanguage('en-US')
    ->withHttpClient($myPsr18Client)
    ->withRequestFactory($requestFactory)
    ->withStreamFactory($streamFactory)
    ->withIdempotencyKeyGenerator($generator);

Error handling

Every failure implements Logipro\Snp\Client\Exception\SnpException.

use Logipro\Snp\Client\Exception\ApiErrorCode;
use Logipro\Snp\Client\Exception\ApiException;
use Logipro\Snp\Client\Exception\RateLimitException;
use Logipro\Snp\Client\Exception\TransportException;
use Logipro\Snp\Client\Exception\ValidationException;

try {
    // …
} catch (ValidationException $e) {
    foreach ($e->getFieldErrors() as $error) {
        echo $error->getPath(), ': ', $error->getMessage(), PHP_EOL;
    }
} catch (RateLimitException $e) {
    sleep($e->getRetryAfter() ?? 60);
} catch (ApiException $e) {
    if ($e->getErrorCode() === ApiErrorCode::CHANNEL_DISCONNECTED) {
        // reconnect via channels()->connect()
    }
} catch (TransportException $e) {
    // network / DNS / TLS
}

The API key is never included in exception messages or var_dump() output.

Webhooks

Verify inbound SNP webhooks with HMAC-SHA256:

use Logipro\Snp\Client\Webhook\WebhookEvent;
use Logipro\Snp\Client\Webhook\WebhookSignatureVerifier;

$verifier = new WebhookSignatureVerifier();
if (!$verifier->verify($rawBody, $signatureHeader, $secret)) {
    http_response_code(401);
    exit;
}
$event = WebhookEvent::fromValues($eventId, $eventType, $payload);

Testing without HTTP

use Logipro\Snp\Client\Testing\MockSnpClientFactory;

$client = MockSnpClientFactory::createDefault();
$brands = $client->brands()->list();

Use MockSnpClientFactory::build() with a custom router for scenario tests (429, disconnected channel, …).

Behat (optional, against a live SNP)

With SNP running locally (./start in the SNP repo) and SNP_API_KEY set. After ./install, dev dependencies include Guzzle so SnpClient::create() can auto-discover a PSR-18 client (integrators still choose their own HTTP stack in production).

export SNP_API_KEY=snp_live_…
export SNP_API_BASE_URL=http://127.0.0.1:10980/api/v1
./bin/behat

Scenarios are skipped when SNP_API_KEY is unset.

Contributing

Requirements: Docker and Git (PHP is not required on the host).

git clone git@gitlab.logipro.com:opensource/snp/php-client.git
cd php-client
./install
./codecheck

See CONTRIBUTING.md. Quality gate: PSR-12, PHPStan level 10, 100 % line coverage on src/, Infection MSI 100 %, PHPUnit on PHP 7.4 and 8.4.

Contract

A frozen copy of the SNP OpenAPI document lives in contract/openapi.yaml (see contract/README.md).

License

MIT