Back to Lead Magnet & Landing Page Follow-up

Integration and API Spec

The reference during the build: every tool connection, auth scope, field mapping, and error-handling rule.

4 pagesPDF · Technical
FS-DOC-05Technical

Integration and API Spec

Lead Magnet & Landing Page Follow-up

[YourCompany.com] · Marketing Department · Prepared by FullSpec · [Today's Date]

This document is the authoritative integration reference for the Lead Magnet and Landing Page Follow-up automation. It covers every tool connected to the workflow, the exact API scopes and auth methods required, field mappings between systems, the orchestration layer design, the credential store structure, and the defined failure behaviour for every integration point. The FullSpec team uses this document during build and testing. It assumes familiarity with REST APIs, webhook configuration, and credential management in a workflow automation context.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agent(s)
Typeform
Landing page form and primary workflow trigger
Webhook (HMAC-SHA256 signature) + Personal Access Token for REST calls
Basic (webhook access included)
Agent 1
HubSpot
CRM: contact deduplication, upsert, tagging, list membership, lead scoring
Private App Token (OAuth 2.0 scopes)
Starter CRM (Contacts API available at free tier; list membership requires Starter)
Agent 1, Agent 2
Mailchimp
Asset delivery transactional email and nurture sequence enrolment
API Key (header-based) + Mandrill API Key for transactional sends
Essentials (automations) + Mandrill add-on for transactional
Agent 2
Google Drive
Asset storage: shareable links retrieved by the orchestration layer and injected into delivery emails
OAuth 2.0 (service account JSON key)
Google Workspace or personal account with Drive API enabled
Agent 2
Google Sheets
Submission tracking log: one row appended per captured contact
OAuth 2.0 (service account JSON key, same project as Drive)
Google Workspace or personal account with Sheets API enabled
Agent 1
Slack
Warm-lead sales alert posted to designated sales channel
Incoming Webhook URL (no OAuth required for posting; Bot Token for channel management)
Free (incoming webhooks available on all plans)
Agent 2
Orchestration layer
Hosts all agent workflows, manages credentials, handles retries and routing logic
Internal credential store; outbound auth per tool above
Determined at build selection
All agents
Before you connect anything: all integrations must be validated in sandbox or test environments before production credentials are introduced. Use Typeform test webhooks, a HubSpot sandbox portal, a Mailchimp test audience, and a private Slack channel for every connection check. Production credentials must never appear in a workflow that has not passed end-to-end QA.

02Per-tool integration detail

Typeform

Typeform is the workflow trigger. Every new form submission fires an HTTP POST webhook to the orchestration layer endpoint. The payload contains all field responses keyed by field reference ID. A Personal Access Token is used only if the orchestration layer needs to backfill missed events via the Responses API.

Auth method
Webhook: HMAC-SHA256 signature header (typeform-signature). PAT for Responses API fallback.
Required scopes (PAT)
responses:read, forms:read
Webhook setup
Add webhook URL under Form > Connect > Webhooks. Enable payload signing and store the secret in the credential store as TYPEFORM_WEBHOOK_SECRET. Select 'form_response' event only. Retry is handled by Typeform automatically (up to 3 attempts with exponential backoff).
Signature validation
On receipt, compute HMAC-SHA256 of raw request body using TYPEFORM_WEBHOOK_SECRET and compare to typeform-signature header value. Reject any request where the signatures do not match and return HTTP 400.
Required configuration
Typeform Form ID stored as TYPEFORM_FORM_ID in the credential store. Field reference IDs for email, first_name, last_name, and lead_magnet_choice must be documented in the field mapping table (Section 03). Do not hardcode field references in workflow logic.
Rate limits
Responses API: 200 requests/minute per token. At ~120 submissions/month (approx. 4/day peak), no throttling is required. Webhook delivery is not rate-limited by Typeform.
Constraints
Webhook payloads expire from Typeform's retry queue after 72 hours. If the orchestration endpoint is unreachable for longer than 72 hours, a manual Responses API backfill job must be triggered. Typeform does not guarantee delivery order for concurrent submissions.
// Inbound webhook payload (key fields)
POST /webhook/typeform-inbound
Headers: typeform-signature: sha256=<hmac>
{
  "form_id": "<TYPEFORM_FORM_ID>",
  "token": "<unique_response_token>",
  "submitted_at": "2024-04-19T10:23:11Z",
  "answers": [
    { "field": { "ref": "email_field_ref" }, "email": "contact@example.com" },
    { "field": { "ref": "first_name_ref" }, "text": "Jane" },
    { "field": { "ref": "last_name_ref" }, "text": "Smith" },
    { "field": { "ref": "magnet_choice_ref" }, "choice": { "label": "SEO Checklist" } }
  ]
}
// Output to Agent 1
{ email, first_name, last_name, lead_magnet_label, submitted_at, response_token }
HubSpot

HubSpot is used by both agents. Agent 1 performs contact deduplication via email lookup, upserts the contact record, applies list membership, sets custom properties for lead source and lead magnet label, and writes an initial lead score. Agent 2 reads the contact's engagement score to determine whether the warm-lead threshold has been crossed.

Auth method
Private App Token passed as Authorization: Bearer <HUBSPOT_PRIVATE_APP_TOKEN> header on all requests.
Required scopes
crm.objects.contacts.read, crm.objects.contacts.write, crm.lists.read, crm.lists.write, crm.schemas.contacts.read, crm.schemas.contacts.write
Webhook/trigger setup
No inbound HubSpot webhook is used in this build. HubSpot is called outbound by the orchestration layer. Engagement score polling for the warm-lead check is performed by Agent 2 on a scheduled interval (every 30 minutes).
Required configuration
HUBSPOT_PORTAL_ID, HUBSPOT_PRIVATE_APP_TOKEN stored in credential store. Custom contact properties that must exist before build: hs_lead_source (string), lead_magnet_label (string), lead_magnet_delivered_at (datetime), nurture_sequence_enrolled (boolean). Target list IDs stored as HUBSPOT_LIST_ID_<MAGNET_SLUG> per magnet. Do not hardcode list IDs in workflow logic.
Deduplication logic
Search contacts by email using GET /crm/v3/objects/contacts/search with filterGroups on email. If a record exists, PATCH the existing contact. If no record exists, POST to /crm/v3/objects/contacts. Always use the returned contact ID (hs_object_id) for all downstream calls.
Rate limits
Private Apps: 150 requests/10 seconds per portal. At 120 submissions/month, peak burst is well below this limit. No throttling logic required, but the orchestration layer must honour 429 responses with a 1-second retry delay.
Constraints
HubSpot list membership via API requires the Starter CRM plan or above. The free tier does not support programmatic list adds. All custom property names must match exactly (case-sensitive, snake_case) as configured in the portal before build begins.
// Deduplication search request
POST /crm/v3/objects/contacts/search
{ "filterGroups": [{ "filters": [{ "propertyName": "email", "operator": "EQ", "value": "<email>" }] }] }
// Upsert (create)
POST /crm/v3/objects/contacts
{ "properties": { "email", "firstname", "lastname", "hs_lead_source", "lead_magnet_label", "lead_magnet_delivered_at", "nurture_sequence_enrolled" } }
// Upsert (update)
PATCH /crm/v3/objects/contacts/<hs_object_id>
// Add to list
POST /contacts/v1/lists/<HUBSPOT_LIST_ID>/contacts/add
{ "vids": [<hs_object_id>] }
// Warm-lead engagement read (Agent 2)
GET /crm/v3/objects/contacts/<hs_object_id>?properties=hs_email_open_count,hs_email_click_count,hubscore
Mailchimp

Mailchimp handles two distinct functions: transactional asset delivery emails (via Mandrill) and nurture sequence enrolment (via Mailchimp Automations). These use separate API surfaces and separate keys. The correct template and sequence are selected based on the lead_magnet_label value passed from Agent 1.

Auth method
Mailchimp Marketing API: apikey query parameter or Authorization: apikey <MAILCHIMP_API_KEY> header. Mandrill transactional: X-MC-APIKEY header with MANDRILL_API_KEY.
Required scopes (Marketing API)
Mailchimp API keys grant full account access; scope restriction is managed by creating a dedicated API key for this integration only. The key must have access to the target audience ID stored as MAILCHIMP_AUDIENCE_ID.
Webhook/trigger setup
No inbound Mailchimp webhook is used for triggering. Enrolment is performed via outbound API call. If Mailchimp engagement webhooks are configured in future for real-time open/click events, the endpoint must validate the secret_key query parameter Mailchimp appends.
Required configuration
MAILCHIMP_API_KEY, MAILCHIMP_AUDIENCE_ID, MANDRILL_API_KEY stored in credential store. Per-magnet template slugs stored as MANDRILL_TEMPLATE_SLUG_<MAGNET_SLUG>. Per-magnet automation workflow IDs stored as MAILCHIMP_WORKFLOW_ID_<MAGNET_SLUG>. MAILCHIMP_DC (data centre suffix, e.g. us21) stored separately and appended to all API base URLs. Google Drive asset URLs stored as GDRIVE_ASSET_URL_<MAGNET_SLUG> and injected as Mandrill template merge variables.
Transactional send (Mandrill)
POST https://mandrillapp.com/api/1.0/messages/send-template with template_name, template_content (merge vars: ASSET_URL, FIRST_NAME, MAGNET_LABEL), and to array containing recipient email and name. Expect HTTP 200 with status 'sent' or 'queued'. Log the _id field returned by Mandrill as mandrill_message_id in Google Sheets.
Nurture enrolment
POST /3.0/automations/<MAILCHIMP_WORKFLOW_ID>/emails/<first_email_id>/queue with { "email_address": "<email>" }. The first email ID for each workflow must be pre-fetched and stored in the credential store as MAILCHIMP_WORKFLOW_EMAIL_ID_<MAGNET_SLUG>.
Rate limits
Marketing API: 10 concurrent connections, no published per-minute cap. Mandrill: 200 sends/second. At 120/month volume, no throttling is needed. The orchestration layer must still respect 429 and 503 responses with exponential backoff.
Constraints
Mailchimp Automations (nurture sequences) must be in 'sending' status before enrolment calls succeed. Paused automations will return a 400 error. Mandrill requires a verified sending domain. Ensure the from-address domain has SPF and DKIM records published before go-live.
// Mandrill transactional send
POST https://mandrillapp.com/api/1.0/messages/send-template
{
  "key": "<MANDRILL_API_KEY>",
  "template_name": "<MANDRILL_TEMPLATE_SLUG_seo-checklist>",
  "template_content": [],
  "message": {
    "to": [{ "email": "contact@example.com", "name": "Jane Smith" }],
    "merge_vars": [{ "rcpt": "contact@example.com", "vars": [
      { "name": "FIRST_NAME", "content": "Jane" },
      { "name": "ASSET_URL", "content": "<GDRIVE_ASSET_URL_seo-checklist>" },
      { "name": "MAGNET_LABEL", "content": "SEO Checklist" }
    ]}]
  }
}
// Nurture enrolment
POST /3.0/automations/<MAILCHIMP_WORKFLOW_ID_seo-checklist>/emails/<MAILCHIMP_WORKFLOW_EMAIL_ID_seo-checklist>/queue
{ "email_address": "contact@example.com" }
Google Drive

Google Drive is not called at runtime for file content. The orchestration layer resolves the correct asset shareable link from a pre-built lookup table stored in the credential store, keyed by magnet slug. The Drive API is used during setup to verify link validity and confirm share permissions. If link rotation is required, a Drive API call updates the lookup table.

Auth method
OAuth 2.0 via service account JSON key (GDRIVE_SERVICE_ACCOUNT_KEY). The service account must be granted 'Viewer' access to each asset file in Drive.
Required scopes
https://www.googleapis.com/auth/drive.readonly (setup and link verification only)
Webhook/trigger setup
No Drive webhook is used in this workflow. Asset URLs are static and stored in the credential store at build time. If assets change, the credential store must be updated manually and FullSpec notified.
Required configuration
GDRIVE_ASSET_URL_<MAGNET_SLUG> entries in the credential store for every active lead magnet. Files must be shared as 'Anyone with the link can view' before build. File IDs must not be hardcoded in workflow logic.
Rate limits
Drive API: 1,000 requests/100 seconds per project. Only used during setup and link verification, not per submission. No throttling required.
Constraints
If a file is moved, renamed, or its sharing settings are changed, the stored URL will break silently. A link-health check job should be run weekly during the first month post-launch. Asset URLs must use the /uc?export=download or direct shareable link format, not the edit or preview URL.
// Link verification (setup only)
GET https://www.googleapis.com/drive/v3/files/<file_id>?fields=id,name,webViewLink,permissions
// Expected: permissions includes { type: 'anyone', role: 'reader' }
// Runtime: no Drive API call. Orchestration layer reads GDRIVE_ASSET_URL_<MAGNET_SLUG> from credential store directly.
Google Sheets

Google Sheets receives one appended row per successful submission, written by Agent 1 after the HubSpot upsert is confirmed. The sheet acts as the operational tracking log and is read by the marketing coordinator for exception review and volume reporting.

Auth method
OAuth 2.0 via service account JSON key (GSHEETS_SERVICE_ACCOUNT_KEY, may share the same service account as Drive if in the same GCP project). Service account must be added as an Editor on the target spreadsheet.
Required scopes
https://www.googleapis.com/auth/spreadsheets
Webhook/trigger setup
No inbound webhook. Agent 1 makes an outbound append call after HubSpot confirmation.
Required configuration
GSHEETS_SPREADSHEET_ID and GSHEETS_SHEET_NAME stored in the credential store. Sheet must have the following header row in columns A through H before build: Timestamp, Email, First Name, Last Name, Lead Magnet, HubSpot Contact ID, Mandrill Message ID, Delivery Status. Do not hardcode the spreadsheet ID in workflow logic.
Rate limits
Sheets API: 300 requests/minute per project, 60 requests/minute per user. At 120/month volume (approx. 4 appends/day), no throttling is required.
Constraints
The service account must have Editor (not Viewer) access on the spreadsheet. Read-only access will cause silent failures on append. If the sheet name is changed after build, the append call will return a 400 error. Sheet name changes must be communicated to FullSpec before being made.
// Append row
POST https://sheets.googleapis.com/v4/spreadsheets/<GSHEETS_SPREADSHEET_ID>/values/<GSHEETS_SHEET_NAME>!A:H:append?valueInputOption=USER_ENTERED
{
  "values": [[
    "<submitted_at>",
    "<email>",
    "<first_name>",
    "<last_name>",
    "<lead_magnet_label>",
    "<hs_object_id>",
    "<mandrill_message_id>",
    "<delivery_status>"
  ]]
}
Slack

Slack receives a single inbound message from Agent 2 when a contact crosses the warm-lead threshold (2 email opens and 1 link click recorded in HubSpot). The message is posted via an Incoming Webhook URL to the designated sales channel. No Slack API read operations are performed by this workflow.

Auth method
Incoming Webhook URL (SLACK_WEBHOOK_URL). The URL encodes authentication and does not require a separate token for posting. Store the full URL in the credential store; do not log it.
Required scopes
incoming-webhook (granted when the Slack App is installed to the workspace and the webhook is created for the target channel)
Webhook/trigger setup
Create a Slack App at api.slack.com/apps. Add the Incoming Webhooks feature. Install the app to the workspace and select the sales channel (e.g. #warm-leads). Copy the generated webhook URL to SLACK_WEBHOOK_URL in the credential store. The channel ID must be stored as SLACK_CHANNEL_ID for audit logging.
Required configuration
SLACK_WEBHOOK_URL and SLACK_CHANNEL_ID in credential store. Message template must include: contact first name, last name, email, lead magnet downloaded, HubSpot contact URL. Do not hardcode the webhook URL in workflow logic.
Rate limits
Incoming Webhooks: 1 message/second per webhook URL. At current volume, warm-lead alerts will be infrequent (a small fraction of 120/month). No throttling required.
Constraints
If the Slack app is uninstalled or the webhook is revoked, posts will fail with HTTP 403. The webhook URL must be rotated in the credential store if the app is reinstalled. The target channel must remain public or the app must be explicitly invited to a private channel.
// Warm-lead alert post
POST <SLACK_WEBHOOK_URL>
{
  "text": "Warm lead alert",
  "blocks": [
    { "type": "section", "text": { "type": "mrkdwn",
      "text": "*<first_name> <last_name>* (<email>) has reached warm-lead threshold.\nMagnet: <lead_magnet_label>\n<hubspot_contact_url>" } }
  ]
}
Integration and API SpecPage 1 of 3
FS-DOC-05Technical

03Field mappings between tools

The tables below define the exact field mappings for each agent handoff. Source and destination field names are shown in monospace. All field names must be used exactly as written; any deviation will cause mapping failures silently or surface as CRM property errors.

Handoff 1: Typeform submission to HubSpot contact (Agent 1, deduplication and upsert step)

Source tool
Source field
Destination tool
Destination field
Typeform
answers[ref=email_field_ref].email
HubSpot
email
Typeform
answers[ref=first_name_ref].text
HubSpot
firstname
Typeform
answers[ref=last_name_ref].text
HubSpot
lastname
Typeform
answers[ref=magnet_choice_ref].choice.label
HubSpot
lead_magnet_label
Typeform
submitted_at
HubSpot
lead_magnet_delivered_at
Orchestration (static)
"Landing Page Form"
HubSpot
hs_lead_source
Orchestration (static)
false
HubSpot
nurture_sequence_enrolled
Typeform
token
HubSpot
typeform_response_token (custom string property)

Handoff 2: HubSpot contact to Mailchimp transactional send (Agent 2, asset delivery step)

Source tool
Source field
Destination tool
Destination field
HubSpot
email
Mailchimp (Mandrill)
message.to[0].email
HubSpot
firstname
Mailchimp (Mandrill)
message.merge_vars[0].vars[name=FIRST_NAME].content
HubSpot
lead_magnet_label
Mailchimp (Mandrill)
template_name (resolved via MANDRILL_TEMPLATE_SLUG_<MAGNET_SLUG>)
Credential store
GDRIVE_ASSET_URL_<MAGNET_SLUG>
Mailchimp (Mandrill)
message.merge_vars[0].vars[name=ASSET_URL].content
HubSpot
lead_magnet_label
Mailchimp (Mandrill)
message.merge_vars[0].vars[name=MAGNET_LABEL].content

Handoff 3: HubSpot contact to Mailchimp nurture enrolment (Agent 2, sequence enrolment step)

Source tool
Source field
Destination tool
Destination field
HubSpot
email
Mailchimp Automations
email_address (queue body)
HubSpot
lead_magnet_label
Orchestration (lookup)
MAILCHIMP_WORKFLOW_ID_<MAGNET_SLUG>
Orchestration (lookup)
MAILCHIMP_WORKFLOW_EMAIL_ID_<MAGNET_SLUG>
Mailchimp Automations
URL path: /automations/<workflow_id>/emails/<email_id>/queue
HubSpot
hs_object_id
Google Sheets
column F: HubSpot Contact ID

Handoff 4: Agent 1 confirmation to Google Sheets tracking log (Agent 1, logging step)

Source tool
Source field
Destination tool
Destination field
Typeform
submitted_at
Google Sheets
column A: Timestamp
HubSpot
email
Google Sheets
column B: Email
HubSpot
firstname
Google Sheets
column C: First Name
HubSpot
lastname
Google Sheets
column D: Last Name
HubSpot
lead_magnet_label
Google Sheets
column E: Lead Magnet
HubSpot
hs_object_id
Google Sheets
column F: HubSpot Contact ID
Mailchimp (Mandrill)
response[0]._id
Google Sheets
column G: Mandrill Message ID
Mailchimp (Mandrill)
response[0].status
Google Sheets
column H: Delivery Status

Handoff 5: HubSpot engagement data to Slack warm-lead alert (Agent 2, warm-lead check)

Source tool
Source field
Destination tool
Destination field
HubSpot
firstname
Slack
blocks[0].text (first_name token)
HubSpot
lastname
Slack
blocks[0].text (last_name token)
HubSpot
email
Slack
blocks[0].text (email token)
HubSpot
lead_magnet_label
Slack
blocks[0].text (lead_magnet_label token)
Orchestration (constructed)
https://app.hubspot.com/contacts/<HUBSPOT_PORTAL_ID>/contact/<hs_object_id>
Slack
blocks[0].text (hubspot_contact_url token)

04Build stack and orchestration

Orchestration layout
Two discrete agent workflows, one per agent. Agent 1 (Lead Capture and Enrichment) and Agent 2 (Asset Delivery and Nurture) run sequentially: Agent 2 is triggered by the successful completion event of Agent 1. Both workflows share a single credential store. No logic is duplicated between workflows.
Agent 1 trigger mechanism
Inbound webhook (HTTP POST) from Typeform. The orchestration layer exposes a public HTTPS endpoint. HMAC-SHA256 signature validation is performed on every incoming request before the workflow proceeds. Invalid signatures are rejected immediately with HTTP 400 and the event is logged.
Agent 2 trigger mechanism
Internal event emitted by Agent 1 on successful HubSpot upsert and Sheets log. Agent 2 begins immediately after Agent 1 completion. The warm-lead polling step within Agent 2 runs on a 30-minute scheduled poll against HubSpot; it is not event-driven from Mailchimp.
Credential store type
Encrypted key-value store native to the orchestration platform. All secrets are referenced by environment variable name. No secret value is written into workflow node configuration directly.
Slug resolution
lead_magnet_label from Typeform is normalised to a URL-safe slug (lowercase, spaces replaced with hyphens) before being used as a lookup key. Example: 'SEO Checklist' resolves to 'seo-checklist'. This slug is used consistently across all MAGNET_SLUG keyed credentials.
Inter-workflow data passing
Agent 1 passes a structured JSON context object to Agent 2 via the internal event payload. This object contains: email, firstname, lastname, lead_magnet_label, magnet_slug, hs_object_id, submitted_at. No additional HubSpot reads are required at the start of Agent 2.
All credential store keys. Values are populated by the FullSpec team before build validation begins. Rotate any compromised value immediately and update the orchestration platform credential store.
// Credential store contents (all entries required before build begins)

// Typeform
TYPEFORM_WEBHOOK_SECRET=<hmac_secret_from_typeform_ui>
TYPEFORM_FORM_ID=<form_id_from_typeform>
TYPEFORM_PAT=<personal_access_token>          // fallback Responses API only

// HubSpot
HUBSPOT_PORTAL_ID=<portal_id>
HUBSPOT_PRIVATE_APP_TOKEN=<private_app_token>
HUBSPOT_LIST_ID_seo-checklist=<list_id>
HUBSPOT_LIST_ID_<magnet_slug>=<list_id>       // one entry per active lead magnet

// Mailchimp / Mandrill
MAILCHIMP_API_KEY=<mailchimp_api_key>
MAILCHIMP_AUDIENCE_ID=<audience_id>
MAILCHIMP_DC=us21                             // replace with actual data centre
MANDRILL_API_KEY=<mandrill_api_key>
MANDRILL_TEMPLATE_SLUG_seo-checklist=lm-asset-seo-checklist
MANDRILL_TEMPLATE_SLUG_<magnet_slug>=<template_slug>  // one per magnet
MAILCHIMP_WORKFLOW_ID_seo-checklist=<automation_workflow_id>
MAILCHIMP_WORKFLOW_EMAIL_ID_seo-checklist=<first_email_id_in_workflow>
MAILCHIMP_WORKFLOW_ID_<magnet_slug>=<workflow_id>     // one per magnet
MAILCHIMP_WORKFLOW_EMAIL_ID_<magnet_slug>=<email_id>  // one per magnet

// Google (shared service account)
GDRIVE_SERVICE_ACCOUNT_KEY=<base64_encoded_service_account_json>
GSHEETS_SERVICE_ACCOUNT_KEY=<base64_encoded_service_account_json>  // may be same key
GSHEETS_SPREADSHEET_ID=<spreadsheet_id>
GSHEETS_SHEET_NAME=Submissions
GDRIVE_ASSET_URL_seo-checklist=https://drive.google.com/uc?export=download&id=<file_id>
GDRIVE_ASSET_URL_<magnet_slug>=<drive_url>    // one per active lead magnet

// Slack
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/<T_ID>/<B_ID>/<token>
SLACK_CHANNEL_ID=<channel_id>

// Warm-lead threshold (configurable without code change)
WARM_LEAD_OPEN_THRESHOLD=2
WARM_LEAD_CLICK_THRESHOLD=1
The warm-lead threshold values (WARM_LEAD_OPEN_THRESHOLD and WARM_LEAD_CLICK_THRESHOLD) are stored as credential store entries so they can be adjusted without a workflow code change. If the threshold is changed, notify the FullSpec team so the QA test cases can be re-validated.
Integration and API SpecPage 2 of 3
FS-DOC-05Technical

05Error handling and retry logic

Every integration point in this workflow has a defined failure behaviour. Unhandled exceptions must never fail silently. Where a retry strategy is defined, the orchestration layer must implement exponential backoff with jitter unless otherwise stated. All failures must be written to the workflow execution log with the full error response body, the step name, and the contact email (masked to first 3 characters plus domain for PII compliance).

Integration
Scenario
Required behaviour
Typeform webhook inbound
HMAC signature validation fails
Reject request immediately. Return HTTP 400. Log the raw headers and the computed signature. Do not proceed with the workflow. Alert the FullSpec team via the platform's error notification channel if 3 or more failures occur within 10 minutes.
Typeform webhook inbound
Webhook payload missing required field (e.g. email is blank)
Halt Agent 1. Append a row to Google Sheets with available fields and 'MISSING_FIELD' in the Delivery Status column. Send an internal error alert. Do not attempt HubSpot upsert.
Typeform Responses API (backfill)
PAT authentication returns 401
Halt backfill job. Log error with timestamp. Alert FullSpec support at support@gofullspec.com. Do not retry automatically; token rotation is required.
HubSpot Contacts API
Rate limit exceeded (429 response)
Pause workflow step. Retry after the Retry-After header value (default 1 second if header absent). Retry up to 5 times with exponential backoff (1s, 2s, 4s, 8s, 16s). If all 5 retries fail, log the contact details to a dead-letter queue and alert FullSpec.
HubSpot Contacts API
Upsert returns 5xx server error
Retry up to 3 times with 5-second intervals. If all retries fail, write the full payload to a dead-letter log and halt Agent 1. Do not proceed to Mailchimp or Sheets steps. Alert FullSpec.
HubSpot list membership API
List ID not found (404) for the resolved magnet slug
Log error with the unresolved slug value. Apply a fallback tag 'list_assignment_failed' to the HubSpot contact. Continue to the Mailchimp and Sheets steps so the contact is not lost. Alert FullSpec so the missing list ID credential can be added.
Mailchimp Mandrill (transactional send)
Template not found (unknown_template error)
Do not retry. Log the missing template slug and the contact email to the dead-letter log. Write 'TEMPLATE_NOT_FOUND' to Google Sheets Delivery Status column. Alert FullSpec. The contact is in HubSpot; the asset can be sent manually by the marketing coordinator from the Sheets log.
Mailchimp Mandrill (transactional send)
Send returns status 'rejected' (invalid email) or 'bounced'
Write 'BOUNCED' or 'REJECTED' to Google Sheets Delivery Status column. Set a HubSpot contact property email_deliverable = false. Flag the contact for the manual exception review step. Do not enrol in nurture sequence.
Mailchimp Automations (nurture enrolment)
Automation is paused (400 response)
Log error with workflow ID. Do not retry automatically. Write 'NURTURE_ENROL_FAILED' to Sheets. Alert FullSpec and the marketing coordinator. The coordinator must manually activate the automation or re-enrol once the sequence is unpaused.
Google Sheets append
Service account lacks write permission (403 response)
Log the failure. Retry once after 10 seconds. If retry fails, write the full row data to the workflow execution log in JSON format so it can be manually pasted into the sheet. Alert FullSpec. Do not halt upstream steps (HubSpot and Mailchimp are already complete).
Slack incoming webhook
Webhook URL returns 403 (revoked or channel deleted)
Log the failure with the contact name and HubSpot URL. Retry once after 30 seconds. If retry fails, write the warm-lead contact details to the workflow execution log and send an email alert to the address stored as FALLBACK_ALERT_EMAIL in the credential store. Do not block or rollback any upstream steps.
HubSpot engagement poll (warm-lead check)
HubSpot returns 5xx or poll job times out
Skip the current poll cycle. Log the failure. The next poll cycle (30 minutes later) will retry automatically. If 3 consecutive poll cycles fail for the same contact, alert FullSpec and pause polling for that contact ID.
Dead-letter log: all payloads that exhaust retries without success must be written to a persistent dead-letter store (a dedicated tab in the Google Sheets tracking log named 'Dead Letter' is acceptable at current volume). The marketing coordinator reviews this tab during the weekly exception review. FullSpec will configure this tab and the append logic during the build phase.
For build questions or integration issues during development, contact the FullSpec team at support@gofullspec.com. Include the workflow name, the step ID, and the full error response body in any support request.
Integration and API SpecPage 3 of 3

More documents for this process

Every document generated for Lead Magnet & Landing Page Follow-up.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Developer Handover Pack
Technical · Developer
View
Test and QA Plan
Quality · Developer
View