Search by

feedple / feedple-sdk

UmarBelloKanwa

Official PHP SDK for the Feedple AI platform

v1.0.30 2026-10-15 22:32 UTC

README

The official PHP SDK for the Feedple AI platform. Connect your database to Feedple AI with minimal setup.

Packagist Version PHP Version License: MIT

Installation

composer require feedple/feedple-sdk

Requirements: PHP >= 8.0 and the pdo extension for your database (pdo_mysql, pdo_pgsql, or pdo_sqlite).

Core Setup in 3 Steps

require __DIR__ . '/vendor/autoload.php';

use Feedple\Sdk\FeedpleSDK;
use Feedple\Sdk\DbConfig;
use Feedple\Sdk\Core\Identity;

// 1. Configure database connection
$dbConfig = DbConfig::mysql(
    host:     '127.0.0.1',
    database: 'myapp',
    username: 'root',
    password: 'secret_password',
);

// 2. Define table access permissions (RBAC)
$identity = new Identity(
    name:          'main-app',
    allTables:     true, // or: allowedTables: ['users', 'orders']
);

// 3. Initialize Feedple SDK
$sdk = new FeedpleSDK(
    apiKey:   getenv('FEEDPLE_API_KEY'),
    dbConfig: $dbConfig,
    identity: $identity,
);

Transport Modes

Feedple supports two execution transports:

1. Webhook Mode (Recommended for Web & APIs)

Stateless and fast (~15–30ms). Requires zero background daemons or event loops. Incoming queries from Feedple Cloud are handled directly via WebhookBridge:

use Feedple\Sdk\Core\WebhookBridge;

$bridge = new WebhookBridge(
    sdk:           $sdk,
    webhookSecret: getenv('FEEDPLE_WEBHOOK_SECRET'),
);

$rawBody = file_get_contents('php://input') ?: '';
$headers = getallheaders() ?: [];

$result = $bridge->handle($rawBody, $headers);

http_response_code($result['status_code']);
header('Content-Type: application/json');
echo json_encode($result['body']);

2. WebSocket Mode (CLI Daemon / Local Dev)

Persistent outbound socket connection. Ideal for CLI workers or local environments behind NAT/firewalls:

$sdk = new FeedpleSDK(
    apiKey:    getenv('FEEDPLE_API_KEY'),
    dbConfig:  $dbConfig,
    identity:  $identity,
    transport: 'websocket',
);

// Start worker (blocks until stopped)
$sdk->run();

// Or stop cleanly from another process/signal:
$sdk->stop();

Auto Transport Selection: When transport is omitted, the SDK defaults to 'websocket' in local development (APP_ENV=local) and 'webhook' in production. If your app is on localhost but targeting Feedple Cloud, 'websocket' is automatically forced so the cloud can reach your database.

Local Development & Testing Guide

1. For Application Developers (Testing Locally)

  • Zero Configuration: The SDK automatically detects local development when APP_ENV=local or when APP_URL points to localhost/127.0.0.1.
  • Automatic WebSocket Selection: Because Feedple Cloud (on the internet) cannot send inbound HTTP webhooks into a private laptop without public tunneling, the SDK's reachability guard automatically routes traffic over WebSocket mode.
  • Running Locally:
    • Zero extra commands: When you run php artisan serve, the SDK automatically hooks in and boots the background WebSocket worker!
    • Or via CLI daemon: Run php artisan feedple:start.

2. For Feedple Platform Developers (Local Backend + Local App)

When testing against a local Feedple AI backend running on http://localhost:8000:

  • Add to .env:

    FEEDPLE_DEV_ENV=true

    This immediately redirects the SDK to http://localhost:8000/api/v1 (REST) and ws://localhost:8000/api/v1/tenants/ws (WebSocket) without touching SDK source code.

  • To Test Webhook Transport Locally:

    FEEDPLE_DEV_ENV=true
    FEEDPLE_TRANSPORT=webhook
    APP_URL=http://127.0.0.1:8001
    1. Start feedple-ai on port 8000: uvicorn app.main:app --port 8000 --reload
    2. Start Laravel on port 8001: php artisan serve --port=8001
    3. Run sync: php artisan feedple:sync Feedple AI on port 8000 will call your webhook bridge directly on port 8001.
  • To Test WebSocket Transport Locally:

    FEEDPLE_DEV_ENV=true
    FEEDPLE_TRANSPORT=websocket

    Start the daemon with php artisan feedple:start to connect to ws://localhost:8000.

Environment Client App Location Feedple Server Default Transport Required Settings
Client Local Dev localhost:8000 Cloud Run WebSocket None (Auto-detected)
Client Production yourdomain.com Cloud Run Webhook None (Auto-detected)
Core Dev (Webhook) 127.0.0.1:8001 localhost:8000 Webhook FEEDPLE_DEV_ENV=true
FEEDPLE_TRANSPORT=webhook
Core Dev (WebSocket) 127.0.0.1:8001 localhost:8000 WebSocket FEEDPLE_DEV_ENV=true
FEEDPLE_TRANSPORT=websocket

Database Configuration (DbConfig)

use Feedple\Sdk\DbConfig;

// PostgreSQL
$db = DbConfig::pgsql(host: '127.0.0.1', database: 'myapp', username: 'postgres', password: 'secret', port: 5432);

// MySQL / MariaDB
$db = DbConfig::mysql(host: '127.0.0.1', database: 'myapp', username: 'root', password: 'secret', port: 3306);

// SQLite
$db = DbConfig::sqlite('/path/to/database.sqlite');

// Custom DSN
$db = DbConfig::raw('sqlsrv:Server=localhost;Database=myapp', username: 'sa', password: 'secret');

Table Access Control (Identity)

Control which database tables Feedple AI is permitted to query:

use Feedple\Sdk\Core\Identity;

// Expose specific tables only (Recommended)
$identity = new Identity(
    name:          'restricted-access',
    allowedTables: ['users', 'orders', 'products'],
);

// Expose all tables
$identity = new Identity(
    name:      'full-access',
    allTables: true,
);

Note: Sensitive columns (password, token, secret, hash, salt, ssn, credit_card) are always excluded automatically.

Schema Synchronization

Upload your database structure (tables, columns, primary & foreign keys) to Feedple:

// HTTP one-shot sync (recommended for deploy scripts / CI)
$result = $sdk->syncSchemaHttp(
    webhookUrl: 'https://myapp.com/api/feedple/bridge',
    force: false,
);

// Sync schema & notify WebSocket if active
$sdk->syncSchema();

Laravel Integration (Zero-Config Auto-Discovery)

The SDK automatically registers the service provider via Laravel Package Discovery. No manual registration in bootstrap/app.php or config/app.php is needed!

  1. Install the SDK:
composer require feedple/feedple-sdk
  1. Add your Feedple API Key to .env:
FEEDPLE_API_KEY=fdpl_live_your_actual_api_key

When you start your development server (php artisan serve), the Feedple background worker daemon starts automatically in < 5ms without blocking.

(Optional) Publish the configuration file if you wish to customize options:

php artisan vendor:publish --tag=feedple-config

Artisan Commands

# Push schema and register webhook bridge
php artisan feedple:sync

# Check worker status
php artisan feedple:status

# Start background worker daemon (WebSocket mode)
php artisan feedple:start
php artisan feedple:start --tail

# Force start daemon even if transport is configured for webhook mode
php artisan feedple:start --force

# Stop background worker daemon
php artisan feedple:stop

Note on Webhook Mode: If your application is configured for Webhook mode (FEEDPLE_TRANSPORT=webhook), running php artisan feedple:start informs you that webhook mode is stateless and does not require a background daemon, directing you to php artisan feedple:sync. Pass --force if you wish to run a WebSocket worker daemon anyway.

Standalone CLI Binary (./vendor/bin/feedple)

For non-Laravel frameworks (Symfony, WordPress, CodeIgniter, Yii) or vanilla PHP projects, the SDK includes a unified CLI binary installed to ./vendor/bin/feedple.

The CLI automatically detects your project's .env file and connects using standard DB_* and FEEDPLE_* environment variables:

# Check status and database connection
./vendor/bin/feedple status
./vendor/bin/feedple status --lines=25

# Synchronize schema and register webhook bridge
./vendor/bin/feedple sync
./vendor/bin/feedple sync --force --bridge-url=https://myapp.com/feedple-bridge.php

# Start persistent WebSocket daemon (with optional live log tailing)
./vendor/bin/feedple start
./vendor/bin/feedple start --tail

# Stop background WebSocket daemon
./vendor/bin/feedple stop

Environment Configuration

By default, the SDK connects to Feedple Cloud:

  • API Base URL: https://feedple-ai-614817435356.us-central1.run.app/api/v1
  • WebSocket URL: wss://feedple-ai-614817435356.us-central1.run.app/api/v1/tenants/ws

To connect to a local Feedple server during development, set in .env:

FEEDPLE_DEV_ENV=true

(Sets API to http://localhost:8000/api/v1 and WebSocket to ws://localhost:8000/api/v1/tenants/ws)

SSL Verification & CA Certificate Bundles

The SDK automatically resolves a bundled Mozilla CA root certificate bundle (resources/cacert.pem), eliminating cURL error 60: SSL certificate problem: unable to get local issuer certificate on Windows (XAMPP/WAMP) and shared hosting.

You can customize SSL behavior in .env:

# Disable SSL certificate verification (e.g. for self-signed certificates or local dev)
FEEDPLE_VERIFY_SSL=false

# Or specify a custom CA bundle path
FEEDPLE_CA_BUNDLE="C:\Server\ssl\cacert.pem"

Core API Reference

FeedpleSDK

namespace Feedple\Sdk;

class FeedpleSDK
{
    public function __construct(
        string            $apiKey,
        DbConfig          $dbConfig,
        Identity          $identity,
        ?string           $autoloadPath       = null,
        bool              $autoSync           = true,
        int               $syncInterval       = 60,
        bool              $reconnectEnabled   = true,
        ?int              $maxRetries         = null,
        bool              $probeBeforeConnect = false,
        ?LoggerInterface  $logger             = null,
        ?string           $runtimeDir         = null,
        bool              $isWorkerProcess    = false,
        ?string           $transport          = null, // 'webhook' | 'websocket'
        ?string           $webhookSecret      = null,
        bool|string|null  $verifySsl          = null, // bool or FEEDPLE_VERIFY_SSL
        ?string           $caBundlePath       = null  // path or FEEDPLE_CA_BUNDLE
    );

    public function run(): void;
    public function stop(): void;
    public function syncSchema(?string $webhookUrl = null): void;
    public function syncSchemaHttp(?string $apiBaseUrl = null, bool $force = false, ?string $webhookUrl = null): array;
    public function executeIr(array $ir): array;
    public function getTransport(): string;
    public function setTransport(string $transport): void;
    public function isSslVerified(): bool;
    public function getCaBundlePath(): ?string;

    // Helpers
    public static function isCliDevServer(): bool;
    public static function isLocalDevTool(): bool;
    public static function isServerEnvironment(): bool;
    public static function isTesting(): bool;
    public static function isDevelopment(): bool;
    public static function isProduction(): bool;
    public static function getDefaultTransport(): string;
    public static function isWebhookReachable(): bool;
    public static function isLocalApp(): bool;
    public static function isLocalUrl(string $url): bool;
    public static function detectAppUrl(?string $explicitUrl = null): ?string;
    public static function detectWebhookUrl(?string $bridgePath = null, ?string $appUrl = null): ?string;
    public static function isValidCaFile(?string $path): bool;
    public static function resolveCaBundle(?string $customPath = null): ?string;
    public static function isSslVerificationEnabled(): bool;
    public static function isDevEnv(): bool;
}

WebhookBridge

namespace Feedple\Sdk\Core;

class WebhookBridge
{
    public function __construct(FeedpleSDK $sdk, ?string $webhookSecret = null, int $tolerance = 300);
    public function handle(string $rawBody, array $headers): array; // ['status_code' => int, 'body' => array]
    public static function verifySignature(string $rawBody, ?string $signatureHeader, string|array|null $secret = null, int $tolerance = 300): array;
}

DbConfig

namespace Feedple\Sdk;

final class DbConfig
{
    public static function mysql(string $host, string $database, ?string $username = null, ?string $password = null, int $port = 3306, string $charset = 'utf8mb4'): self;
    public static function pgsql(string $host, string $database, ?string $username = null, ?string $password = null, int $port = 5432): self;
    public static function sqlite(string $path): self;
    public static function raw(string $dsn, ?string $username = null, ?string $password = null, array $options = []): self;
    public function toPdo(): \PDO;
}

Identity

namespace Feedple\Sdk\Core;

class Identity
{
    public function __construct(?string $name = null, array $allowedTables = [], bool $allTables = false);
}

License

MIT License.