Typeform ExecModule
Overview
TypeformModule connects ValkyrAI workflows to Typeform's Create, Responses, Workspaces, and Webhooks APIs. It exposes 13 bounded operations through the native map I/O ExecModule ABI and keeps the OAuth or personal access token in a READY IntegrationAccount.
The module fixes the provider origin to https://api.typeform.com, sends credentials only in an Authorization bearer header, validates resource identities, returns one page per execution, retries transient reads only, and sends mutations once. Permanent deletes require confirmDelete: true; the full-form PUT operation separately requires confirmReplaceForm: true because omitted form fields can be removed.
n8n's Typeform trigger pattern informed the webhook-first intake flow: register a stable callback, receive response events, and retrieve complete submissions through the Responses API. ValkyrAI adds a generated IntegrationAccount boundary, public-HTTPS webhook validation, bounded data handling, mutation reconciliation, destructive guards, and shared credential redaction.
Usage
- Create a Typeform OAuth grant or personal access token with only the scopes needed by the workflow.
- Store the token in the encrypted
apiKeyfield of a ValkyrAIIntegrationAccount, set the account status toREADY, and bind it throughExecModuleConfig.authConfig.integrationAccount. - Choose one operation and provide its conditional fields.
- For workspace and form lists, pass
nextPageinto a later execution whenhasMoreis true. - For responses, persist
nextCursorand send it ascursoron the next execution. Do not silently exhaust a form's entire history. - Keep response delivery behind a stable, public HTTPS webhook endpoint. Retrieve the complete response after an event when downstream processing needs all answers.
Inputs
| Name | Type | Required | Description | Constraints |
|---|---|---|---|---|
operation | string | Yes | One operation listed below. | Exact allowlist of 13 values. |
formId | string | Conditional | Typeform form identifier. | 3–128 letters, digits, _, or -. |
webhookTag | string | Conditional | Stable webhook identifier. | 1–64 letters, digits, _, or -. |
payload | object | Conditional | Form definition or webhook configuration. | Non-empty; at most 20 allowlisted top-level fields and 512 KiB serialized. |
responseIds | array | delete_responses | Response tokens selected for deletion. | 1–100 validated tokens. |
page | integer | No | One-based workspace/form page. | 1–1,000; default 1. |
pageSize | integer | No | Provider page size. | 1–200; default 25. |
workspaceId | string | No | Restrict list_forms to one workspace. | At most 128 characters. |
search | string | No | Typeform form-title search. | At most 200 characters. |
orderBy | string | No | Form ordering. | created_at or last_updated_at. |
cursor | string | No | Typeform response token used as after. | At most 128 characters. |
since / until | string | No | Response time-window bounds. | Provider-supported timestamp strings up to 64 characters. |
query | string | No | Typeform response full-text query. | At most 200 characters. |
completed | boolean | No | Include completed or incomplete responses. | Provider boolean. |
sort | string | No | Response order. | submitted_at,asc or submitted_at,desc. |
confirmReplaceForm | boolean | update_form | Acknowledge complete replacement semantics. | Must be true. |
confirmDelete | boolean | Delete operations | Acknowledge permanent or delivery-changing deletion. | Must be true. |
Form payloads allow Typeform's title, type, theme, workspace, settings, thankyou_screens, fields, logic, hidden, variables, welcome_screens, endings, and calculations top-level fields. Create and update require a non-empty title. Webhook payloads allow url, enabled, and verify_ssl; the URL must be public HTTPS without embedded credentials, a query, or a fragment.
Outputs
| Name | Type | When present | Description |
|---|---|---|---|
status | string | Always | success or error. |
operation | string | Always | Normalized operation. |
data | object | Single-resource success | Verified account, form, or webhook object. |
id | string | Form/webhook success | Verified form ID or webhook tag. |
items | array | List success | One bounded provider page. |
count | integer | List/delete success | Returned items or selected deletions. |
total | integer | Provider supplies it | Provider-reported total items. |
hasMore | boolean | List success | Whether another bounded page may exist. |
nextPage | integer | Workspace/form page remains | Next one-based page. |
nextCursor | string | Response page remains | Last response token for a later after cursor. |
deleted | boolean | Successful delete | Confirms the provider accepted the delete. |
httpStatus | integer | Provider call | Typeform HTTP status. |
attempts | integer | Provider call or error | HTTP attempts consumed. |
error | object | Failure | Redacted code, message, and retryable fields. |
Responses can contain names, email addresses, contact details, file links, hidden fields, tracking values, and free text. The module classifies all provider output as restricted and never copies response content into progress logs.
IntegrationAccount Requirements
| Setting | Requirement |
|---|---|
| Provider | Typeform API |
| Authentication | OAuth 2 bearer token or personal access token |
| Status | Exactly READY |
accountName | Human-readable Typeform account or integration identity |
apiKey | Encrypted access token, 16–4,096 non-whitespace characters |
| Relationship | ExecModuleConfig.authConfig.integrationAccount |
| Suggested scopes | Minimum subset of accounts:read, workspaces:read, forms:read, forms:write, responses:read, responses:write, webhooks:read, and webhooks:write |
OAuth applications should request offline only when their separate authorization lifecycle needs a refresh token. OAuth initiation, callback processing, refresh, revocation, and webhook-signing-secret storage remain outside this module.
Configuration
Illustrative persisted configuration:
{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:typeform-lead-intake"
},
"payloadConfig": {
"parameters": "{\"operation\":\"list_responses\",\"formId\":\"leadForm01\",\"pageSize\":25,\"completed\":true}"
}
}
The relationship is symbolic. The generated IntegrationAccount record owns the encrypted token.
Operations
| Operation | Typeform path | Behavior |
|---|---|---|
get_account | GET /me | Read the authenticated account profile. |
list_workspaces | GET /workspaces | Return one bounded workspace page. |
list_forms | GET /forms | Return one bounded page with optional workspace/search/order filters. |
get_form | GET /forms/{formId} | Retrieve a form and verify its ID. |
create_form | POST /forms | Create one allowlisted form definition; single-attempt. |
update_form | PUT /forms/{formId} | Replace the complete form after explicit acknowledgement; single-attempt. |
delete_form | DELETE /forms/{formId} | Permanently delete a form after explicit acknowledgement; single-attempt. |
list_responses | GET /forms/{formId}/responses | Retrieve one bounded response page with cursor, time, query, completion, and sort filters. |
delete_responses | DELETE /forms/{formId}/responses | Permanently delete 1–100 selected response tokens after explicit acknowledgement; single-attempt. |
list_webhooks | GET /forms/{formId}/webhooks | Retrieve all webhooks for one form. |
get_webhook | GET /forms/{formId}/webhooks/{tag} | Retrieve and verify one webhook. |
upsert_webhook | PUT /forms/{formId}/webhooks/{tag} | Create or update one public-HTTPS webhook; single-attempt. |
delete_webhook | DELETE /forms/{formId}/webhooks/{tag} | Stop that webhook's delivery after explicit acknowledgement; single-attempt. |
Themes, images, workspace membership writes, form messages, webhook delivery history, contacts, automations, insights, audio/video processing, embeds, OAuth lifecycle, and provider-hosted MCP operations are deferred.
Errors and Failure Modes
| Failure | Cause | Retry guidance |
|---|---|---|
VALIDATION_ERROR | Missing or invalid operation/ID/body/filter/cursor, unsafe webhook URL, missing acknowledgement, secret-like payload field, or invalid provider response. | Correct the request; local validation sends no provider call. |
INTEGRATION_ACCOUNT_REQUIRED | No bound secure account. | Bind the intended Typeform account. |
INTEGRATION_ACCOUNT_NOT_READY | Account status is not READY. | Repair or reauthorize the account. |
TYPEFORM_HTTP_400 / 409 | Invalid form schema, cursor, conflicting tag, or provider constraint. | Correct the payload or reconcile current provider state. |
TYPEFORM_HTTP_401 / 403 | Token invalid, expired, or missing the required scope. | Reauthorize with the minimum required scopes. |
TYPEFORM_HTTP_404 | Form, response selection, or webhook is unavailable. | Verify the account and resource identifiers. |
TYPEFORM_HTTP_429 | Provider rate limit exceeded. | Reads honor bounded numeric Retry-After; mutations remain single-attempt. |
TYPEFORM_HTTP_5xx / NETWORK_ERROR | Provider or transport failure. | Reads retry up to three total attempts. Reconcile mutations before manual retry. |
RESPONSE_TOO_LARGE | Provider response exceeded 5 MiB. | Narrow filters or page size. |
Provider errors are bounded to 500 characters and pass through token replacement plus the shared sensitive-data policy. A timed-out create, replacement, deletion, or webhook upsert may have reached Typeform, so automatic write replay is disabled.
Example
Retrieve new completed responses after a saved token:
{
"operation": "list_responses",
"formId": "leadForm01",
"pageSize": 25,
"cursor": "response-token-previous",
"completed": true,
"sort": "submitted_at,asc"
}
Expected normalized result:
{
"status": "success",
"operation": "list_responses",
"items": [
{
"token": "response-token-new",
"submitted_at": "2026-08-12T12:00:00Z",
"answers": []
}
],
"count": 1,
"total": 2,
"hasMore": true,
"nextCursor": "response-token-new",
"httpStatus": 200,
"attempts": 1
}
Persist nextCursor only after downstream processing commits successfully. The module does not own cross-execution exactly-once delivery.
Notes
- Pagination: workspace and form lists use
pagepluspage_size. Response lists use one boundedaftercursor. The module never silently follows all pages. - Rate limits: Typeform can return
429. Safe reads retry at most three total attempts and honor a bounded numericRetry-After; all writes remain single-attempt. - API limits: page size is capped at 200, request bodies at 512 KiB, and response bodies at 5 MiB. Response deletion is capped at 100 explicit tokens per execution.
- Idempotency: reads are transport-retryable. Webhook
PUTtargets a stable form/tag pair but is still sent once because timeouts are ambiguous. Form creates, replacements, and all deletes are single-attempt. - Destructive behavior:
delete_formanddelete_responsesare permanent. Typeform support cannot recover deleted responses.update_formreplaces the full form, so omitted fields may be removed.delete_webhookstops future delivery but does not remove existing response data. - Webhook safety: only public HTTPS destinations are accepted; loopback, private address literals,
.localhosts, embedded credentials, nonstandard ports, queries, and fragments are rejected. DNS rebinding protection remains the responsibility of the outbound network policy. - Privacy: responses may contain personal and sensitive data. Apply consent, purpose limitation, retention, deletion, suppression, and human-review rules before sending data to CRM, messaging, or AI modules.
- External verification: deterministic tests cover validation, bearer authentication, request construction, form replacement/deletion guards, response pagination, permanent-delete batching, webhook URL safety, transient read retry, mutation non-retry, redaction, identity checks, fixed-origin routing, normalization, and annotation discovery. Live Typeform authentication, plan limits, scopes, form rendering, response delivery, and webhook callbacks require separately authorized provider credentials and are not exercised in repository tests.
See the official n8n Typeform Trigger, Typeform developer platform, OAuth scope table, Workspaces guide, and Responses deletion guidance for functional and provider references.