emailfunnelai / sdk-laravel
Laravel integration for the Email Funnel AI SDK — facade, config, and auto-wired client.
Requires
- php: ^8.1
- ext-curl: *
- ext-json: *
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- orchestra/testbench: ^8.22|^9.0|^10.0
This package is auto-updated.
Last update: 2026-07-22 08:28:06 UTC
README
Official Laravel package for the Email Funnel AI
integration API. Ships a self-contained client with a service provider, a
facade, and publishable config — credentials come from your .env, and the
client is auto-wired into the container.
- Laravel 10, 11, 12
- Auto-discovered provider +
EmailFunnelAifacade - Fully standalone — the only dependency is
illuminate/support
Installation
composer require emailfunnelai/laravel
Publish the config (optional):
php artisan vendor:publish --tag=emailfunnelai-config
Set your credentials in .env:
EMAILFUNNELAI_PROJECT_KEY=pk_your_project_key EMAILFUNNELAI_PROJECT_SECRET=sk_your_secret_key # Optional — defaults to https://app.emailfunnel.ai. # Set only for staging, a self-hosted instance, or local development. # EMAILFUNNELAI_BASE_URL=http://127.0.0.1:8000
Usage
Via the facade:
use EmailFunnelAi\Laravel\Facades\EmailFunnelAi; EmailFunnelAi::validate(); $list = EmailFunnelAi::lists()->create('Newsletter signups'); EmailFunnelAi::contacts() ->sync(['email' => 'jane@example.com', 'source_type' => 'app']) ->toList($list['id']); EmailFunnelAi::analytics()->dashboard();
Or resolve the client from the container / inject it:
use EmailFunnelAi\Laravel\Client; public function __construct(private Client $emailFunnel) {} // ... $this->emailFunnel->bindings()->all();
The full resource surface is contacts, lists, bindings, fieldMappings,
autoTagging, analytics, and sso, plus a top-level validate.
Responses & errors
Successful calls return the unwrapped data payload as an array. Any error
response raises a typed exception:
use EmailFunnelAi\Laravel\Exceptions\ApiException; use EmailFunnelAi\Laravel\Exceptions\TransportException; try { EmailFunnelAi::contacts()->sync(['email' => 'invalid'])->toList($listId); } catch (ApiException $e) { $e->status; // 422 $e->errorType; // "validation_error" $e->messages; // ['contact.email' => ['The email field is required.']] $e->retryAfter; // set on 429 rate limits } catch (TransportException $e) { // network / timeout failure (no HTTP response) }
Branch on errorType for specific conditions — e.g. a contact list that has been
deactivated rejects new members with a 409 list_inactive:
try { EmailFunnelAi::contacts()->sync($contact)->toList($listId); } catch (ApiException $e) { if ($e->errorType === 'list_inactive') { // The target list is inactive — reactivate it or pick another list. } }
Common errorType values
errorType |
Status | Meaning |
|---|---|---|
invalid_credentials |
401 | Missing/invalid project key or secret |
inactive_project |
403 | The connected project is inactive |
validation_error |
422 | Request body failed validation (messages set) |
invalid_email / suppressed |
422 | Email is undeliverable or suppressed |
list_inactive |
409 | Target contact list is inactive and rejects new members |
rate_limit_exceeded |
429 | 1000 req/hour cap hit (retryAfter set) |
sync_failed |
500 | Unexpected sync failure |
Transport & testing
By default the package sends requests through Laravel's HTTP client, so
Http::fake(), retries, logging, and any global middleware apply to SDK calls:
use Illuminate\Support\Facades\Http; use EmailFunnelAi\Laravel\Facades\EmailFunnelAi; Http::fake([ '*/api/v1/saas/contacts' => Http::response(['data' => ['contact_id' => 7]], 201), ]); EmailFunnelAi::contacts()->sync(['email' => 'jane@example.com', 'source_type' => 'app'])->toList($listId); Http::assertSent(fn ($request) => $request->url() === 'https://app.emailfunnel.ai/api/v1/saas/contacts');
Need a different transport (e.g. a zero-dependency cURL client, a PSR-18 client,
or custom logging)? Bind your own EmailFunnelAi\Laravel\Http\HttpClient:
use EmailFunnelAi\Laravel\Http\CurlHttpClient; use EmailFunnelAi\Laravel\Http\HttpClient; $this->app->instance(HttpClient::class, new CurlHttpClient());
Testing
composer install
composer test
Tests use Orchestra Testbench with a recording transport — no network — and a coverage test asserts the facade exposes every documented endpoint.
License
MIT © Email Funnel AI