pyrx/synapse

Official PHP SDK for PYRX Synapse - CRM, email, and event tracking API

Maintainers

Package info

github.com/PYRX-Tech/pyrx-synapse-php

Homepage

pkg:composer/pyrx/synapse

Statistics

Installs: 8

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-05-01 16:18 UTC

This package is auto-updated.

Last update: 2026-05-02 03:45:26 UTC


README

CI Latest Stable Version License: MIT PHP Version

Official PHP SDK for PYRX Synapse -- CRM, email, and event tracking API.

Zero runtime dependencies. Uses PHP's built-in curl, json, and hash extensions.

Requirements

  • PHP >= 8.1
  • ext-curl
  • ext-json

Installation

composer require pyrx/synapse

Quick Start

use PyrxSynapse\Client;

$client = new Client(
    apiKey: 'psk_live_your_api_key',
    workspaceId: 'ws_your_workspace_id',
);

// Track an event
$result = $client->track(
    externalId: 'user_123',
    eventName: 'purchase',
    attributes: ['amount' => 99.99, 'currency' => 'USD'],
);
echo $result['event_id']; // "evt_..."

// Identify a contact
$contact = $client->identify(
    externalId: 'user_123',
    email: 'jane@example.com',
    firstName: 'Jane',
    lastName: 'Doe',
    properties: ['plan' => 'pro'],
    tags: ['paying', 'onboarded'],
);

// Send a transactional email
$email = $client->sendEmail(
    templateSlug: 'welcome',
    to: ['email' => 'jane@example.com'],
    attributes: ['name' => 'Jane'],
);

Configuration

$client = new Client(
    apiKey: 'psk_live_...',          // Required
    workspaceId: 'ws_...',           // Required
    baseUrl: 'https://synapse-api.pyrx.tech', // Optional (default)
    timeout: 30,                     // Optional, seconds (default: 30)
    maxRetries: 3,                   // Optional (default: 3)
);

// Environment is auto-detected from the API key prefix
echo $client->environment; // "live", "test", or "unknown"

Tracking Events

// Single event
$result = $client->track(
    externalId: 'user_123',
    eventName: 'page_view',
    attributes: ['page' => '/pricing'],
    idempotencyKey: 'idk_unique_123',
    occurredAt: '2026-01-15T10:30:00Z',
);

// Batch events
$result = $client->trackBatch([
    ['external_id' => 'user_1', 'event_name' => 'login'],
    ['external_id' => 'user_2', 'event_name' => 'signup'],
]);
echo $result['accepted']; // 2

Managing Contacts

// Identify (create or update)
$contact = $client->identify(
    externalId: 'user_123',
    email: 'jane@example.com',
    firstName: 'Jane',
);

// Batch identify
$result = $client->identifyBatch(
    contacts: [
        ['external_id' => 'u1', 'email' => 'a@example.com'],
        ['external_id' => 'u2', 'email' => 'b@example.com'],
    ],
    onConflict: 'update',
);

// List contacts
$list = $client->contacts->list(page: 1, perPage: 20, search: 'jane');

// Get a contact
$contact = $client->contacts->get('contact_id');

// Update a contact
$updated = $client->contacts->update('user_123', ['email' => 'new@example.com']);

// Delete a contact
$client->contacts->delete('user_123');

Email Templates

// List templates
$templates = $client->templates->list();

// Get a template
$template = $client->templates->get('welcome');

// Create a template
$template = $client->templates->create([
    'name' => 'Welcome Email',
    'slug' => 'welcome',
    'subject' => 'Welcome, {{name}}!',
    'body_html' => '<h1>Hello {{name}}</h1>',
]);

// Update a template
$updated = $client->templates->update('welcome', ['subject' => 'Hey {{name}}!']);

// Preview a template
$preview = $client->templates->preview('welcome', [
    'attributes' => ['name' => 'Jane'],
]);
echo $preview['html'];

// Delete a template
$client->templates->delete('old-template');

Webhook Verification

Verify incoming webhooks from Synapse using HMAC-SHA256 (Svix format):

use PyrxSynapse\Webhooks;

$payload = file_get_contents('php://input');
$headers = [
    'svix-id' => $_SERVER['HTTP_SVIX_ID'] ?? '',
    'svix-timestamp' => $_SERVER['HTTP_SVIX_TIMESTAMP'] ?? '',
    'svix-signature' => $_SERVER['HTTP_SVIX_SIGNATURE'] ?? '',
];

try {
    $event = Webhooks::verify($payload, $headers, 'whsec_your_webhook_secret');
    // $event is the parsed JSON payload
    echo $event['type']; // e.g., "contact.created"
} catch (\InvalidArgumentException $e) {
    http_response_code(400);
    echo $e->getMessage();
}

Error Handling

use PyrxSynapse\Errors\SynapseError;
use PyrxSynapse\Errors\SynapseAuthError;
use PyrxSynapse\Errors\SynapseRateLimitError;
use PyrxSynapse\Errors\SynapsePlanLimitError;
use PyrxSynapse\Errors\SynapseValidationError;

try {
    $client->track('user_1', 'event');
} catch (SynapseAuthError $e) {
    // 401 or 403 (not plan limit)
    echo "Auth error: {$e->getMessage()} (status: {$e->status})";
} catch (SynapseRateLimitError $e) {
    // 429
    echo "Rate limited. Retry after {$e->retryAfter} seconds.";
} catch (SynapsePlanLimitError $e) {
    // 403 with code "plan_limit_reached"
    echo "Plan limit: {$e->current}/{$e->maximum} {$e->limitType} on {$e->plan} plan";
} catch (SynapseValidationError $e) {
    // 422
    foreach ($e->errors as $error) {
        echo "{$error['field']}: {$error['message']}\n";
    }
} catch (SynapseError $e) {
    // Any other API error
    echo "Error: {$e->getMessage()} (status: {$e->status}, code: {$e->errorCode})";
}

Retry Behavior

The client automatically retries on:

  • HTTP 429, 500, 502, 503, 504
  • curl connection errors (timeout, connection refused)

Backoff: min(1.0 * 2^attempt, 30s) + random jitter (0-0.5s). For 429 responses, the Retry-After header value is used instead.

Non-retryable errors (401, 403, 422, etc.) are raised immediately.

License

MIT