Skip to main content

Requirements

  • PHP 8.0 or higher
  • Composer
  • ext-json
  • ext-curl

Installation

Install the EnviaAI SDK using Composer:
composer require enviaai/sdk

Quick Start

<?php
require 'vendor/autoload.php';

use EnviaAI\EnviaAI;

$client = new EnviaAI('your-api-key');

// Send a message
$response = $client->messages->send([
    'instanceId' => 'inst_abc123',
    'to' => '5511999999999',
    'message' => 'Hello from EnviaAI!'
]);

echo "Message ID: " . $response->messageId;

Configuration

Client Options

use EnviaAI\EnviaAI;

$client = new EnviaAI('your-api-key', [
    'baseUrl' => 'https://api.enviaai.app',  // Optional
    'timeout' => 30,                          // Optional, timeout in seconds
    'maxRetries' => 3                         // Optional
]);

Environment Variables

The SDK can read from environment variables:
export ENVIAAI_API_KEY=your-api-key
export ENVIAAI_BASE_URL=https://api.enviaai.app
// API key is read from ENVIAAI_API_KEY
$client = new EnviaAI();

Messages API

Send Text Message

$response = $client->messages->send([
    'instanceId' => 'inst_abc123',
    'to' => '5511999999999',
    'message' => 'Hello! How can I help you?'
]);

Send Media Message

// Image
$imageResponse = $client->messages->send([
    'instanceId' => 'inst_abc123',
    'to' => '5511999999999',
    'mediaUrl' => 'https://example.com/image.jpg',
    'mediaType' => 'image',
    'caption' => 'Check this out!'
]);

// Document
$docResponse = $client->messages->send([
    'instanceId' => 'inst_abc123',
    'to' => '5511999999999',
    'mediaUrl' => 'https://example.com/document.pdf',
    'mediaType' => 'document',
    'filename' => 'invoice.pdf'
]);

// Audio
$audioResponse = $client->messages->send([
    'instanceId' => 'inst_abc123',
    'to' => '5511999999999',
    'mediaUrl' => 'https://example.com/audio.mp3',
    'mediaType' => 'audio'
]);

Get Message Status

$status = $client->messages->getStatus('msg_xyz789');
echo $status->status; // 'sent', 'delivered', 'read', 'failed'

List Chats

$chats = $client->messages->getChats([
    'instanceId' => 'inst_abc123',
    'limit' => 20,
    'unreadOnly' => true
]);

foreach ($chats->data as $chat) {
    echo "{$chat->contactName}: {$chat->unreadCount} unread\n";
}

Get Chat Messages

$messages = $client->messages->getChatMessages([
    'instanceId' => 'inst_abc123',
    'chatId' => 'chat_def456',
    'limit' => 50
]);

Instances API

List Instances

$instances = $client->instances->list();

foreach ($instances->data as $instance) {
    echo "{$instance->name}: {$instance->status}\n";
}

Get Instance Status

$status = $client->instances->getStatus('inst_abc123');

if ($status->data->status === 'connected') {
    echo "Connected as {$status->data->phone}";
} elseif ($status->data->status === 'qr_pending') {
    echo "Scan QR: {$status->data->qrCode}";
}

Connect Instance

$client->instances->connect('inst_abc123');

// Poll for QR code
$status = $client->instances->getStatus('inst_abc123');
if ($status->data->qrCode) {
    // Display QR code to user
}

Disconnect Instance

$client->instances->disconnect('inst_abc123');

Webhooks API

Create Webhook

$webhook = $client->webhooks->create([
    'url' => 'https://myapp.com/webhooks/enviaai',
    'events' => ['message.received', 'message.delivered'],
    'secret' => 'my-webhook-secret'
]);

List Webhooks

$webhooks = $client->webhooks->list();

Update Webhook

$client->webhooks->update('wh_abc123', [
    'events' => ['message.received', 'message.delivered', 'message.read']
]);

Delete Webhook

$client->webhooks->delete('wh_abc123');

Verify Webhook Signature

use EnviaAI\EnviaAI;

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_ENVIAAI_SIGNATURE'] ?? '';

$isValid = EnviaAI::verifyWebhookSignature(
    $payload,
    $signature,
    'your-webhook-secret'
);

if (!$isValid) {
    http_response_code(401);
    exit('Invalid signature');
}

Error Handling

use EnviaAI\EnviaAI;
use EnviaAI\Exceptions\EnviaAIException;
use EnviaAI\Exceptions\AuthenticationException;
use EnviaAI\Exceptions\RateLimitException;
use EnviaAI\Exceptions\ValidationException;
use EnviaAI\Exceptions\NotFoundException;

$client = new EnviaAI('your-api-key');

try {
    $response = $client->messages->send([
        'instanceId' => 'inst_abc123',
        'to' => '5511999999999',
        'message' => 'Hello!'
    ]);
} catch (RateLimitException $e) {
    echo "Rate limited. Retry after {$e->getRetryAfter()} seconds";
} catch (AuthenticationException $e) {
    echo "Invalid API key";
} catch (ValidationException $e) {
    echo "Validation error: {$e->getMessage()}";
} catch (NotFoundException $e) {
    echo "Resource not found";
} catch (EnviaAIException $e) {
    echo "API Error: {$e->getErrorCode()} - {$e->getMessage()}";
}

Exception Types

Exception ClassDescription
EnviaAIExceptionBase exception for all API errors
AuthenticationExceptionInvalid or missing API key
RateLimitExceptionRate limit exceeded
ValidationExceptionInvalid request parameters
NotFoundExceptionResource not found
ServerExceptionInternal server error

Pagination

// Manual pagination
$offset = 0;
$limit = 50;
$allChats = [];

do {
    $response = $client->messages->getChats([
        'instanceId' => 'inst_abc123',
        'limit' => $limit,
        'offset' => $offset
    ]);

    $allChats = array_merge($allChats, $response->data);
    $offset += $limit;

} while ($response->pagination->hasMore);

// Using iterator
foreach ($client->messages->iterateChats(['instanceId' => 'inst_abc123']) as $chat) {
    echo $chat->contactName . "\n";
}

Logging

Enable debug logging with PSR-3 compatible loggers:
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use EnviaAI\EnviaAI;

$logger = new Logger('enviaai');
$logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));

$client = new EnviaAI('your-api-key', [
    'logger' => $logger
]);

Examples

Laravel Webhook Handler

// routes/api.php
Route::post('/webhooks/enviaai', [WebhookController::class, 'handle']);

// app/Http/Controllers/WebhookController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use EnviaAI\EnviaAI;

class WebhookController extends Controller
{
    private EnviaAI $client;

    public function __construct()
    {
        $this->client = new EnviaAI(config('services.enviaai.key'));
    }

    public function handle(Request $request)
    {
        $signature = $request->header('X-EnviaAI-Signature');

        if (!EnviaAI::verifyWebhookSignature(
            $request->getContent(),
            $signature,
            config('services.enviaai.webhook_secret')
        )) {
            return response()->json(['error' => 'Invalid signature'], 401);
        }

        $event = $request->all();

        if ($event['event'] === 'message.received') {
            // Auto-reply
            $this->client->messages->send([
                'instanceId' => $event['data']['instanceId'],
                'to' => $event['data']['from'],
                'message' => "Thanks for your message! We'll get back to you soon."
            ]);
        }

        return response()->json(['status' => 'ok']);
    }
}

// config/services.php
return [
    'enviaai' => [
        'key' => env('ENVIAAI_API_KEY'),
        'webhook_secret' => env('ENVIAAI_WEBHOOK_SECRET'),
    ],
];

Symfony Webhook Handler

// src/Controller/WebhookController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use EnviaAI\EnviaAI;

class WebhookController extends AbstractController
{
    private EnviaAI $client;

    public function __construct()
    {
        $this->client = new EnviaAI($_ENV['ENVIAAI_API_KEY']);
    }

    #[Route('/webhooks/enviaai', methods: ['POST'])]
    public function handle(Request $request): JsonResponse
    {
        $signature = $request->headers->get('X-EnviaAI-Signature');

        if (!EnviaAI::verifyWebhookSignature(
            $request->getContent(),
            $signature,
            $_ENV['ENVIAAI_WEBHOOK_SECRET']
        )) {
            return new JsonResponse(['error' => 'Invalid signature'], 401);
        }

        $event = json_decode($request->getContent(), true);

        if ($event['event'] === 'message.received') {
            $this->client->messages->send([
                'instanceId' => $event['data']['instanceId'],
                'to' => $event['data']['from'],
                'message' => "Thanks for your message!"
            ]);
        }

        return new JsonResponse(['status' => 'ok']);
    }
}

Bulk Message Sending

use EnviaAI\EnviaAI;
use GuzzleHttp\Promise\Utils;

$client = new EnviaAI('your-api-key');

$contacts = [
    ['phone' => '5511999999999', 'name' => 'John'],
    ['phone' => '5521988888888', 'name' => 'Jane'],
    // ... more contacts
];

// Using Guzzle promises for concurrent requests
$promises = [];
foreach ($contacts as $contact) {
    $promises[] = $client->messages->sendAsync([
        'instanceId' => 'inst_abc123',
        'to' => $contact['phone'],
        'message' => "Hello {$contact['name']}! Check out our new products."
    ]);
}

$results = Utils::settle($promises)->wait();

$success = 0;
$failed = 0;

foreach ($results as $result) {
    if ($result['state'] === 'fulfilled') {
        $success++;
    } else {
        $failed++;
    }
}

echo "Sent: $success, Failed: $failed\n";

Queue Integration (Laravel)

// app/Jobs/SendWhatsAppMessage.php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use EnviaAI\EnviaAI;

class SendWhatsAppMessage implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        private string $instanceId,
        private string $to,
        private string $message
    ) {}

    public function handle(): void
    {
        $client = new EnviaAI(config('services.enviaai.key'));

        $client->messages->send([
            'instanceId' => $this->instanceId,
            'to' => $this->to,
            'message' => $this->message
        ]);
    }

    public function failed(\Throwable $exception): void
    {
        // Log failure
        \Log::error('WhatsApp message failed', [
            'to' => $this->to,
            'error' => $exception->getMessage()
        ]);
    }
}

// Usage
SendWhatsAppMessage::dispatch('inst_abc123', '5511999999999', 'Hello!');

Resources