Integrations

Creating Integrations

Build custom integrations using the generic base classes.

New integrations typically require minimal provider-specific code. The generic base classes handle HTTP requests, field mapping, error handling, and connection testing.

API Integration

Extend GenericApiIntegration for integrations that write data to an external API using API keys or tokens.

<?php

namespace FilaForms\Integrations\Integrations\EmailMarketing;

use FilaForms\Integrations\Integrations\Shared\GenericApiIntegration;
use FilaForms\Integrations\Models\FormIntegration;
use FilaForms\Integrations\Models\IntegrationConnection;

class MailchimpIntegration extends GenericApiIntegration
{
    public function getKey(): string
    {
        return 'mailchimp';
    }

    public function getName(): string
    {
        return 'Mailchimp';
    }

    public function getDescription(): string
    {
        return 'Add form submissions as subscribers to your Mailchimp audience.';
    }

    public function getIcon(): string
    {
        return 'heroicon-o-envelope';
    }

    protected function getApiEndpoint(FormIntegration $integration): string
    {
        $listId = $integration->config['list_id'];
        $dc = $integration->config['data_center'];

        return "https://{$dc}.api.mailchimp.com/3.0/lists/{$listId}/members";
    }

    public function getAuthHeaders(IntegrationConnection $connection): array
    {
        return [
            'Authorization' => 'Bearer ' . $connection->credentials['api_key'],
        ];
    }

    protected function buildPayload(array $mappedData): array
    {
        return [
            'email_address' => $mappedData['email'] ?? '',
            'status' => 'subscribed',
            'merge_fields' => collect($mappedData)
                ->except('email')
                ->toArray(),
        ];
    }

    public function getFieldMappingSchema(): array
    {
        return [
            'email' => ['label' => 'Email Address', 'required' => true],
            'FNAME' => ['label' => 'First Name'],
            'LNAME' => ['label' => 'Last Name'],
        ];
    }
}

The base class provides these methods automatically:

  • handle() -- processes events with field mapping and error handling
  • writeData() -- sends HTTP POST with auth headers from the linked IntegrationConnection
  • test() -- validates connection and sends test payload
  • mapFormFields() -- applies field mapping configuration
  • validateConfig() / validateConnection() -- overridable validation

OAuth Integration

Extend GenericOAuthIntegration for integrations requiring OAuth 2.0 authentication:

<?php

namespace FilaForms\Integrations\Integrations\CRM;

use FilaForms\Integrations\Integrations\Shared\GenericOAuthIntegration;
use FilaForms\Integrations\Models\IntegrationConnection;

class SalesforceIntegration extends GenericOAuthIntegration
{
    public function getKey(): string
    {
        return 'salesforce';
    }

    public function getName(): string
    {
        return 'Salesforce';
    }

    public function getDescription(): string
    {
        return 'Create leads and contacts in Salesforce from form submissions.';
    }

    public function getIcon(): string
    {
        return 'heroicon-o-cloud';
    }

    public function getOAuthScopes(): array
    {
        return ['api', 'refresh_token'];
    }

    protected function getOAuthBaseUrl(): string
    {
        return 'https://login.salesforce.com/services/oauth2';
    }

    protected function getTokenUrl(): string
    {
        return 'https://login.salesforce.com/services/oauth2/token';
    }

    protected function getClientId(): string
    {
        return config('filaforms-integrations.crm.salesforce.client_id');
    }

    protected function getClientSecret(): string
    {
        return config('filaforms-integrations.crm.salesforce.client_secret');
    }

    // ... getApiEndpoint(), buildPayload(), getFieldMappingSchema(), etc.
}

The OAuth base class adds on top of GenericApiIntegration:

  • requiresConnection() -- returns true
  • requiresOAuth() -- returns true
  • getOAuthConfig() -- builds OAuth configuration from your methods
  • buildOAuthRedirectUrl() -- generates the OAuth authorization URL
  • exchangeOAuthCode() -- exchanges auth code for tokens and stores them
  • refreshOAuthToken() -- handles token refresh automatically
  • getAuthHeaders() -- returns Bearer token headers using OAuthTokenManager
  • afterOAuthCallback() -- hook for post-callback logic (scope validation, fetching account email)

Auto-Discovery

Place your integration class in the appropriate subdirectory under src/Integrations/:

src/Integrations/
    Payments/
    EmailMarketing/     <- MailchimpIntegration goes here
    CRM/                <- SalesforceIntegration goes here
    Storage/
    Webhook/
    Automation/
    Shared/             <- Base classes (don't put integrations here)

When auto_discover is enabled, the package automatically finds and registers your integration.

Connection Architecture

Integrations that require external accounts use the two-tier connection system:

  1. IntegrationConnection -- Created on the Integrations page. Stores OAuth tokens/credentials in encrypted credentials column. Can be reused across forms.
  2. FormIntegration -- Created per-form. References a connection_id and stores integration-specific config (field mapping, spreadsheet selection, etc.).

When building an OAuth integration, authentication headers are resolved from the IntegrationConnection, not the FormIntegration:

// GenericOAuthIntegration resolves auth from the connection
public function getAuthHeaders(IntegrationConnection $connection): array
{
    $token = $this->tokenManager->getValidToken($connection);

    return [
        'Authorization' => 'Bearer ' . $token,
    ];
}
Copyright © 2026