Creating Integrations
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 handlingwriteData()-- sends HTTP POST with auth headers from the linkedIntegrationConnectiontest()-- validates connection and sends test payloadmapFormFields()-- applies field mapping configurationvalidateConfig()/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()-- returnstruerequiresOAuth()-- returnstruegetOAuthConfig()-- builds OAuth configuration from your methodsbuildOAuthRedirectUrl()-- generates the OAuth authorization URLexchangeOAuthCode()-- exchanges auth code for tokens and stores themrefreshOAuthToken()-- handles token refresh automaticallygetAuthHeaders()-- returns Bearer token headers usingOAuthTokenManagerafterOAuthCallback()-- 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:
IntegrationConnection-- Created on the Integrations page. Stores OAuth tokens/credentials in encryptedcredentialscolumn. Can be reused across forms.FormIntegration-- Created per-form. References aconnection_idand 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,
];
}