Typeform Connector
Connect Typeform to Brevo through Tajo to automatically sync form responses, capture leads from conversational forms, and trigger marketing automations based on survey submissions and quiz results.
Overview
| Property | Value |
|---|---|
| Platform | Typeform |
| Category | Forms & Surveys (Custom) |
| Setup Complexity | Easy |
| Official Integration | No |
| Data Synced | Responses, Contacts, Events, Forms |
| Auth Method | OAuth 2.0 / Personal Access Token |
Features
- Real-time response sync - Automatically capture form submissions via webhooks
- Contact creation - Create or update Brevo contacts from form responses
- Lead scoring - Use quiz scores and form data for lead qualification
- Hidden Fields - Pass customer data via Hidden Fields for personalized forms
- Conditional mapping - Map different form fields based on response logic
- Multi-form support - Connect multiple typeforms to different Brevo lists
Prerequisites
Before you begin, ensure you have:
- A Typeform account (Basic plan or above for webhooks)
- A Personal Access Token from Typeform Account Settings
- A Brevo account with API access
- A Tajo account with connector permissions
Authentication
Personal Access Token
# Generate a token at https://admin.typeform.com/account#/section/tokensexport TYPEFORM_ACCESS_TOKEN=tfp_your_personal_access_tokenexport TAJO_API_KEY=your_tajo_api_keyexport BREVO_API_KEY=your_brevo_api_keyOAuth 2.0
// OAuth 2.0 Authorization Flowconst authUrl = 'https://api.typeform.com/oauth/authorize?' + new URLSearchParams({ client_id: process.env.TYPEFORM_CLIENT_ID, redirect_uri: 'https://your-app.com/callback', scope: 'forms:read responses:read webhooks:write accounts:read', state: generateState() });
// Exchange authorization code for access tokenconst tokenResponse = await fetch('https://api.typeform.com/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', code: authorizationCode, client_id: process.env.TYPEFORM_CLIENT_ID, client_secret: process.env.TYPEFORM_CLIENT_SECRET, redirect_uri: 'https://your-app.com/callback' })});Configuration
Basic Setup
connectors: typeform: enabled: true access_token: "${TYPEFORM_ACCESS_TOKEN}"
forms: - form_id: "abc123" list_id: 5 mapping: email_field: "email" name_field: "full_name" - form_id: "xyz789" list_id: 6 mapping: email_field: "work_email"
sync: responses: true contacts: true events: true
webhook: enabled: true secret: "${TYPEFORM_WEBHOOK_SECRET}"Field Mapping
field_mapping: # Map Typeform field references to Brevo attributes email: email name: FIRSTNAME company: COMPANY phone: SMS score: LEAD_SCORE quiz_result: QUIZ_SCORE nps_rating: NPS_SCORE feedback: LAST_FEEDBACKAPI Endpoints
| Endpoint | Method | Description |
|---|---|---|
https://api.typeform.com/forms | GET | List all forms |
https://api.typeform.com/forms/{form_id} | GET | Retrieve a form |
https://api.typeform.com/forms | POST | Create a form |
https://api.typeform.com/forms/{form_id} | PUT | Update a form |
https://api.typeform.com/forms/{form_id}/responses | GET | Retrieve responses |
https://api.typeform.com/forms/{form_id}/responses | DELETE | Delete responses |
https://api.typeform.com/forms/{form_id}/webhooks/{tag} | PUT | Create/update webhook |
https://api.typeform.com/forms/{form_id}/webhooks/{tag} | GET | Get webhook |
https://api.typeform.com/forms/{form_id}/webhooks | GET | List webhooks |
Code Examples
Initialize Connector
import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({ apiKey: process.env.TAJO_API_KEY, brevoApiKey: process.env.BREVO_API_KEY});
await tajo.connectors.connect('typeform', { accessToken: process.env.TYPEFORM_ACCESS_TOKEN, forms: ['abc123', 'xyz789']});Retrieve Form Responses
// Fetch responses using the Responses APIconst response = await fetch( 'https://api.typeform.com/forms/abc123/responses?' + new URLSearchParams({ page_size: 25, since: '2024-01-01T00:00:00Z', completed: 'true' }), { headers: { 'Authorization': `Bearer ${process.env.TYPEFORM_ACCESS_TOKEN}` } });
const data = await response.json();
// Sync each response to Brevofor (const item of data.items) { const answers = item.answers; const email = answers.find(a => a.field.ref === 'email')?.email;
if (email) { await tajo.contacts.sync({ email, attributes: { FIRSTNAME: answers.find(a => a.field.ref === 'name')?.text, LEAD_SCORE: item.calculated?.score || 0 }, listIds: [5] }); }}Set Up Webhooks
// Register a webhook for real-time response notificationsawait fetch( 'https://api.typeform.com/forms/abc123/webhooks/tajo-sync', { method: 'PUT', headers: { 'Authorization': `Bearer ${process.env.TYPEFORM_ACCESS_TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ url: 'https://api.tajo.io/webhooks/typeform', enabled: true, secret: process.env.TYPEFORM_WEBHOOK_SECRET }) });Handle Webhook Events
app.post('/webhooks/typeform', async (req, res) => { // Verify webhook signature const signature = req.headers['typeform-signature']; const isValid = verifyTypeformSignature( req.rawBody, signature, process.env.TYPEFORM_WEBHOOK_SECRET );
if (!isValid) return res.status(401).send('Unauthorized');
const { form_response } = req.body;
await tajo.connectors.handleWebhook('typeform', { topic: 'form_response', payload: form_response });
res.status(200).send('OK');});Rate Limits
| Endpoint | Rate Limit | Notes |
|---|---|---|
| Create API | 2 requests/sec | Form creation and updates |
| Responses API | 2 requests/sec | Response retrieval |
| Webhooks API | 2 requests/sec | Webhook management |
| All endpoints | 120 requests/min | Global rate limit |
Response Pagination
The Responses API returns a maximum of 1,000 responses per request. Use the before or after cursor parameters for pagination when retrieving large response sets.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Webhook not received | Webhook disabled | Enable webhook in Typeform dashboard |
| Missing responses | Filter applied | Check since/until and completed params |
| Auth error 401 | Token expired | Generate new Personal Access Token |
| Rate limit 429 | Too many requests | Implement request throttling |
| Empty answers | Optional fields | Handle null/undefined answer values |
Debug Mode
connectors: typeform: debug: true log_level: verbose log_webhooks: true log_responses: trueBest Practices
- Use webhooks - Prefer webhooks over polling for real-time response capture
- Validate signatures - Always verify webhook signatures for security
- Use Hidden Fields - Pre-populate known customer data in forms
- Map field references - Use stable field
refvalues instead of field IDs - Handle partial responses - Account for optional and skipped questions
- Set up retry logic - Implement idempotent webhook processing
Security
- OAuth 2.0 - Scoped token-based authentication
- Webhook signatures - SHA-256 HMAC signature validation
- HTTPS only - All API endpoints require TLS
- Token scoping - Request minimum required OAuth scopes
- Secret management - Store tokens in environment variables or secret managers
- GDPR compliance - Use the Delete Responses API for data erasure requests
Related Resources
Open-Source Implementation Map
No official open-source repository was found in the current Tajo connector catalog for Typeform. Keep this page focused on the verified public API contract and vendor documentation until an official schema, SDK, MCP server, or public integration repository is available.
Tajo Revamp Checklist
- Verify authentication and scope requirements against the vendor documentation before each connector release.
- Document primary sync objects, external IDs, pagination strategy, and rate limits explicitly.
- Add smoke tests from public API examples rather than undocumented behavior.
- Capture webhook signature verification and replay protection when the vendor supports webhooks.
- Record gaps where no official public repository or schema exists so future maintainers know what still needs source-backed validation.