leadpush / sdk-php
Official PHP SDK for Leadpush
Requires
- php: ^8.2
- symfony/http-client: ^7.4
Requires (Dev)
- pestphp/pest: ^3.0|^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-28 16:25:41 UTC
README
Official PHP SDK for the Leadpush API.
Create a Leadpush account at leadpush.io.
Installation
composer require leadpush/sdk-php
Requirements
- PHP 8.2 or newer
- A Leadpush API key
Quick Start
<?php use Leadpush\SDK\Leadpush; $client = new Leadpush($_ENV['LEADPUSH_API_KEY']); $contacts = $client->contacts()->list([ 'page' => 1, 'per_page' => 10, ]); print_r($contacts->data());
Configuration
<?php use Leadpush\SDK\Leadpush; $client = new Leadpush('leadpush_api_key', [ 'baseUrl' => 'https://api.leadpush.io/v1', 'timeout' => 30000, 'headers' => [ 'X-App-Name' => 'my-app', ], ]);
Defaults:
baseUrl:https://api.leadpush.io/v1timeout:30000
You can pass a Symfony HttpClientInterface as the third constructor argument for custom transports or tests.
Contacts
Contact methods that accept a contact identifier can use either the contact uuid or the workspace identity field value, such as an email address.
List Or Search Contacts
$contacts = $client->contacts()->list([ 'search' => 'person@example.com', 'filters' => [ ['id' => 'subscribed', 'value' => [true]], ['id' => 'provider', 'value' => ['gmail']], ], 'page' => 1, 'perPage' => 25, ]);
per_page remains supported for compatibility. Contact lists are limited to 25 records per page.
Supported filters are subscribed with boolean values and provider with Leadpush inbox-provider identifiers.
Get A Contact
$contact = $client->contacts()->get('contact_uuid'); $sameContact = $client->contacts()->get('person@example.com'); echo $contact->uuid(); echo $contact->attributes()['email'];
Create A Contact
$contact = $client->contacts()->create([ 'subscribed' => true, 'attributes' => [ 'email' => 'person@example.com', 'first_name' => 'Person', ], ]);
Update A Contact
$contact = $client->contacts()->update('contact_uuid', [ 'subscribed' => false, 'attributes' => [ 'first_name' => 'Updated', ], ]); $client->contacts()->update('person@example.com', [ 'subscribed' => true, ]);
Update From A Model
$contact = $client->contacts()->get('contact_uuid'); $contact->setSubscribed(false); $contact->setAttribute('first_name', 'Updated'); $contact->update();
Subscribe Or Unsubscribe
$client->contacts()->subscribe('person@example.com'); $client->contacts()->unsubscribe('person@example.com'); $contact->subscribe(); $contact->unsubscribe();
Contact Events
$events = $client->contacts()->events('contact_uuid')->list([ 'search' => 'purchase', ]); $sameEvents = $client->contacts()->events('person@example.com')->list();
You can also access events from an attached contact model:
$contact = $client->contacts()->get('contact_uuid'); $events = $contact->events()->list();
Create A Contact Event
$client->contacts()->events('contact_uuid')->create([ 'event_name' => 'purchase', 'attributes' => [ 'plan' => 'enterprise', ], ]); $client->contacts()->events('person@example.com')->create([ 'event_name' => 'purchase', ]);
Contact event creation returns null when the API accepts the event. The create endpoint does not return the created event.
Pagination
List One Page
$page = $client->contacts()->list([ 'page' => 1, 'per_page' => 25, ]); print_r($page->data()); echo $page->meta()->hasNext() ? 'more' : 'done';
Iterate Every Model
foreach ($client->contacts()->listAll(['per_page' => 25]) as $contact) { echo $contact->uuid(); }
Iterate Page By Page
foreach ($client->contacts()->cursor(['per_page' => 25]) as $page) { echo $page->meta()->currentPage(); echo count($page->data()); }
Workspace
$overview = $client->workspace()->get(); echo $overview['workspace']['uuid']; echo $overview['role']; echo $overview['counts']['contacts'];
The workspace is always derived from the API key. Workspace identifiers are not accepted as request parameters.
Campaigns
List And Get Campaigns
$campaigns = $client->campaigns()->list([ 'search' => 'welcome', 'statuses' => ['draft', 'running'], 'page' => 1, 'perPage' => 25, ]); $campaign = $client->campaigns()->get('campaign_uuid');
Campaign lists are limited to 25 records per page.
Campaign Metrics
$range = [ 'start' => '2026-10-01T00:00:00Z', 'end' => '2026-10-31T23:59:59Z', 'unit' => 'day', ]; $metrics = $client->campaigns()->metrics('campaign_uuid', $range);
Inspect A Campaign Execution
$inspection = $client ->campaigns() ->executions('campaign_uuid') ->get('execution_uuid', 25); echo $inspection['execution']['status']; print_r($inspection['recent_steps']); print_r($inspection['error']);
Execution inspection returns at most 25 recent steps and a sanitized error. It does not expose provider credentials, raw message bodies, internal payloads, or stack traces.
Delivery Metrics
$delivery = $client->metrics()->delivery([ 'start' => '2026-10-01T00:00:00Z', 'end' => '2026-10-31T23:59:59Z', 'unit' => 'day', ]); echo $delivery['summary']['delivered_count']; print_r($delivery['series']);
Campaign and delivery metric requests use daily buckets and may span at most 90 days.
Recent Activity
$activity = $client->activity()->list([ 'eventTypes' => ['contact_created', 'contact_updated'], 'search' => 'person@example.com', 'since' => '2026-10-01T00:00:00Z', 'page' => 1, 'perPage' => 25, ]); print_r($activity['data']);
Activity lists are limited to 25 records per page and return a safe subject projection without raw activity attributes.
Read Endpoint Reference
These paths are relative to the configured /v1 API base URL.
| SDK operation | REST endpoint |
|---|---|
workspace()->get() |
GET /workspace |
contacts()->list(...) |
GET /contacts |
contacts()->get($id) |
GET /contacts/{contact} |
campaigns()->list(...) |
GET /campaigns |
campaigns()->get($id) |
GET /campaigns/{campaign} |
campaigns()->metrics($id, $range) |
GET /campaigns/{campaign}/metrics |
campaigns()->executions($id)->get($executionId) |
GET /campaigns/{campaign}/executions/{execution} |
metrics()->delivery($range) |
GET /metrics/delivery |
activity()->list(...) |
GET /activity |
Domains
List Domains
$domains = $client->domains()->list([ 'search' => 'example', 'page' => 1, 'per_page' => 10, ]);
Create A Domain
$domain = $client->domains()->create([ 'name' => 'example.com', 'dkim_selectors' => ['default'], 'tracking_subdomain' => 'click', 'tracking_mode' => 'cloudflare', ]); print_r($domain->dns());
Verify Or Delete A Domain
$verified = $client->domains()->verify($domain->uuid()); $client->domains()->delete($domain->uuid());
You can also verify or delete from an attached domain model:
$domain = $client->domains()->get('domain_uuid'); $domain->verify(); $domain->delete();
Domain Addresses
$addresses = $client->domains()->addresses('domain_uuid')->list(); $address = $client->domains()->addresses('domain_uuid')->create([ 'address' => 'sender', 'display_name' => 'Sender Name', 'reply_to' => 'reply@example.com', 'company_address' => '123 Main St', 'company_city' => 'New York', 'company_state' => 'NY', 'company_zip' => '10001', 'company_country' => 'US', ]); $client->domains()->addresses('domain_uuid')->delete($address->uuid());
You can also access addresses from an attached domain model:
$domain = $client->domains()->get('domain_uuid'); $addresses = $domain->addresses()->list();
Emails
Send An Email
$send = $client->emails()->send([ 'from' => 'sender@example.com', 'subject' => 'Developer API email', 'html' => '<p>Hello world</p>', 'text' => 'Hello world', 'to' => [ 'known@example.com', 'other@example.com', ], 'bcc' => [ 'audit@example.com', ], 'reply_to' => 'reply@example.com', 'headers' => [ 'X-Correlation-ID' => 'abc-123', 'Auto-Submitted' => 'auto-generated', ], ]); echo $send->isAccepted() ? 'accepted' : 'rejected'; echo $send->messageCount(); echo $send->messages()[0]['uuid'];
The from address must be a verified sendable address in the API key workspace. Provide html, text, or both, and at least one recipient across to and bcc. Leadpush creates one tracked message per unique recipient and returns those message identifiers with initial pending status.
Fields
List Fields
$fields = $client->fields()->list([ 'search' => 'company', 'filters' => [ [ 'id' => 'type', 'value' => ['text'], ], ], ]);
Create A Field
$field = $client->fields()->create([ 'name' => 'company_name', 'type' => 'text', 'format' => [ 'text' => 'url', ], ]);
Suppressions
List Suppressions
$suppressions = $client->suppressions()->list([ 'search' => 'blocked@example.com', 'filters' => [ [ 'id' => 'type', 'value' => ['manual'], ], ], ]);
Create A Suppression
$suppression = $client->suppressions()->create([ 'email' => 'blocked@example.com', 'type' => 'manual', ]);
Suppressions do not support updates. Calling $client->suppressions()->update(...) throws UnsupportedEndpointError.
Low-Level Requests
Use get, post, or delete for endpoints that do not have a typed resource yet.
GET
$response = $client->get('contacts/contact_uuid/events');
POST
$response = $client->post('contacts/contact_uuid/subscribe');
DELETE
$client->delete('contacts/contact_uuid');
Paths can also be passed as arrays:
$client->get(['contacts', 'contact_uuid', 'events']);
Errors
The SDK throws typed errors for common API failures:
<?php use Leadpush\SDK\Exceptions\UnauthorizedError; use Leadpush\SDK\Exceptions\ValidationError; try { $client->contacts()->list(); } catch (UnauthorizedError) { echo 'Invalid API key'; } catch (ValidationError $error) { print_r($error->response()); }
Available errors:
ApiErrorUnauthorizedErrorForbiddenErrorNotFoundErrorValidationErrorTimeoutErrorUnsupportedEndpointError
Development
composer install
composer test
Releasing
Releases are created from Git tags. Packagist reads the GitHub repository and publishes Composer versions from tags like v1.0.0.
Before the first release, submit this repository to Packagist as leadpush/sdk-php and enable the Packagist GitHub integration so new tags update automatically.
To publish a release:
- Open the
Releaseworkflow in GitHub Actions. - Run it manually with a SemVer tag like
v1.0.0. - Wait for the matrix tests to pass.
The workflow creates and pushes the Git tag, then creates a GitHub Release. Packagist will expose the tag as the matching Composer version.
License
MIT