logipro / snp-php-client
PHP client for the SocialNetworksPublisher (SNP) external API
Requires
- php: >=7.4
- ext-json: *
- php-http/discovery: ^1.19
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1 || ^2.0
Requires (Dev)
- behat/behat: ^3.13
- guzzlehttp/guzzle: ^7.8
- nyholm/psr7: ^1.8
- php-http/mock-client: ^1.6
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^9.6
- squizlabs/php_codesniffer: ^3.10
Suggests
None
Provides
None
Conflicts
None
Replaces
None
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
| Accessor | Operations |
|---|---|
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).