Back to Lost Lead Re-engagement

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

Lost Lead Re-engagement

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

This document is the authoritative integration reference for the Lost Lead Re-engagement automation. It covers every tool connected to the orchestration layer, the exact authentication method and OAuth scopes required for each, field-level mappings between agent handoffs, the credential store structure, and defined error handling behaviour for every integration point. The FullSpec team uses this document to build, configure, and validate all connections. No credentials should be hardcoded in workflow logic; all secrets are stored in the centralised credential store as described in section 04.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agents
HubSpot
CRM data source, activity logging, lifecycle stage updates
OAuth 2.0 (private app token)
Sales Hub Starter or above
Agent 1, Agent 2, Agent 3
Gmail
Outbound email sending and inbound reply monitoring
OAuth 2.0 (Google workspace)
Google Workspace Business Starter
Agent 2, Agent 3
OpenAI
AI email drafting and reply intent scoring
API key (Bearer token)
Pay-as-you-go or Team plan
Agent 2, Agent 3
Slack
Warm reply alerts to assigned sales rep
OAuth 2.0 (bot token)
Free or paid Slack workspace
Agent 3
Google Sheets
Sequence tracking and audit log
OAuth 2.0 (service account or user OAuth)
Any Google Workspace tier
Agent 1
Orchestration layer
Connects all tools; hosts credential store; schedules and triggers agent workflows
Per-tool credentials stored in platform vault
Determined at build time
All agents
Before you connect anything: provision sandbox or test credentials for every tool listed above and validate each connection end-to-end in a non-production environment before switching to live production credentials. For HubSpot, use a sandbox portal. For Gmail, use a test Google Workspace account. For OpenAI and Slack, use development tokens scoped to test resources only. Never paste production secrets into workflow logic directly.

02Per-tool integration detail

HubSpot

CRM of record. Used by Agent 1 to query inactive contacts, by Agent 2 to read contact context and log sent emails, and by Agent 3 to update lifecycle stage on sequence completion or warm reply.

Auth method
OAuth 2.0 via HubSpot Private App token. Generate the token inside HubSpot Settings > Integrations > Private Apps. Store the resulting bearer token in the credential store as HUBSPOT_API_TOKEN. Do not use legacy API keys.
Required scopes
crm.objects.contacts.read, crm.objects.contacts.write, crm.objects.deals.read, crm.objects.deals.write, crm.schemas.contacts.read, timeline.events.write, sales-email-read
Webhook / trigger setup
No inbound webhook used from HubSpot. Agent 1 polls the Contacts API on a scheduled daily basis at 07:00 AM using a filter query (lastmodifieddate, hs_last_sales_activity_timestamp). HubSpot does not need to push events outbound for this automation.
Required configuration
Create a custom contact property: re_engagement_sequence_step (number, integer). Create a second custom property: re_engagement_last_sent_date (date). The inactivity threshold list filter must target contacts where hs_last_sales_activity_timestamp is more than 21 days ago AND lifecyclestage is not closedwon AND lifecyclestage is not closedlost. Pipeline stage IDs must be resolved via the Pipelines API and stored as constants in the credential store, not hardcoded as display names.
Rate limits
HubSpot enforces 100 requests per 10 seconds and 40,000 requests per day on Starter plans. At 40 to 80 leads per month, daily batch queries will not exceed 500 API calls per day. No throttling logic is required at current volume, but the orchestration layer should implement a 200 ms inter-request delay as a safety buffer.
Constraints
Private App tokens do not expire but must be rotated manually on compromise. The Contacts Search API (v3) must be used for filter queries; the legacy v1 list endpoints are deprecated. Activity logging must use the Engagements API (v1) or the Timeline Events API (v3); direct object writes via the Contacts API do not create timeline entries.
Gmail

Outbound email channel and inbound reply monitor. Agent 2 sends re-engagement emails from the assigned rep's Gmail account. Agent 3 monitors the same inbox for replies to tracked threads.

Auth method
OAuth 2.0. Each rep's Gmail account must individually authorise the automation via a Google OAuth consent flow. Store per-rep refresh tokens in the credential store keyed as GMAIL_REFRESH_TOKEN_{REP_ID}. The orchestration layer exchanges the refresh token for a short-lived access token at runtime.
Required scopes
https://www.googleapis.com/auth/gmail.send, https://www.googleapis.com/auth/gmail.readonly, https://www.googleapis.com/auth/gmail.modify
Webhook / trigger setup
Use the Gmail Push Notifications API (Gmail API v1: users.watch) to subscribe the inbox to Google Cloud Pub/Sub. The Pub/Sub topic delivers a notification to the orchestration layer's inbound webhook endpoint when a new message arrives matching the label filter INBOX. The watch subscription expires every 7 days and must be automatically renewed by a scheduled sub-workflow. Validate inbound Pub/Sub messages using the Google-signed JWT in the Authorization header before processing.
Required configuration
Apply a Gmail label named re-engagement-tracked to every outbound thread at send time using the labels.create and messages.modify endpoints. Agent 3 filters inbound notifications to only threads carrying this label. Store the Pub/Sub topic ARN as GMAIL_PUBSUB_TOPIC in the credential store. The from address for each send must match the authenticated rep account; do not send from a shared alias without explicit authorisation.
Rate limits
Gmail API enforces 250 quota units per user per second and a daily sending limit of 2,000 messages per Google Workspace account. At current volume of 40 to 80 leads per month across a three-touch sequence, maximum daily sends are approximately 8 to 12 per rep. No per-request throttling is needed; spread batch sends across a 30-minute window after trigger to avoid burst spikes.
Constraints
OAuth refresh tokens can be revoked if the user changes their Google password or revokes app access. The orchestration layer must detect 401 responses and surface an alert via Slack rather than failing silently. CAN-SPAM compliance requires a physical mailing address and unsubscribe mechanism in every outbound email; these must be included in every prompt template output and validated before send.
OpenAI

AI inference layer. Agent 2 calls the Chat Completions API to generate personalised re-engagement email copy for each sequence touch. Agent 3 calls the same API to score reply intent.

Auth method
API key authentication. Pass the key as a Bearer token in the Authorization header on every request. Store as OPENAI_API_KEY in the credential store. Never embed the key in prompt templates or log it to the audit sheet.
Required scopes
No OAuth scopes apply. The API key must belong to an organisation with access to the chat/completions endpoint and the gpt-4o model (or gpt-4-turbo as fallback). Confirm model availability in the OpenAI console before build.
Webhook / trigger setup
No webhook. All calls are synchronous HTTP POST requests to https://api.openai.com/v1/chat/completions made by the orchestration layer at runtime. The orchestration layer waits for the response before proceeding.
Required configuration
System prompt templates for email drafting (three variants: touch_1, touch_2, touch_3) and for reply scoring (one template: reply_classifier) must be stored as versioned templates in the credential or configuration store, not hardcoded in workflow nodes. The model parameter, temperature (0.7 for email drafting, 0.2 for scoring), and max_tokens (600 for email, 100 for scoring) must be externalised as configuration values. The reply_classifier prompt must instruct the model to return a JSON object with a single field: intent, with allowed values of interested, neutral, unsubscribe, or out_of_office.
Rate limits
OpenAI enforces rate limits by tier; at the pay-as-you-go tier, limits are typically 500 RPM and 30,000 TPM for gpt-4o. At 40 to 80 leads per month, peak daily calls are under 20. No throttling is required. Monitor token usage in the OpenAI dashboard monthly to stay within the $25/month budget allocation.
Constraints
OpenAI does not retain API request data for training by default on paid accounts, but confirm the data retention setting in the organisation privacy settings before go-live. The orchestration layer must validate that the model response contains a non-empty choices[0].message.content field before passing output downstream. A malformed or empty response must trigger a retry, not a silent skip.
Slack

Alert delivery channel. Agent 3 posts a structured message to the assigned rep's Slack channel or direct message when a warm reply is detected.

Auth method
OAuth 2.0 bot token. Install the Slack app to the workspace via the OAuth flow and store the resulting bot token as SLACK_BOT_TOKEN in the credential store. The bot requires the chat:write scope at minimum.
Required scopes
chat:write, chat:write.public (if posting to channels the bot has not joined), users:read (to resolve rep Slack user IDs from email addresses stored in HubSpot)
Webhook / trigger setup
Outbound only. The orchestration layer calls the Slack Web API endpoint chat.postMessage with the bot token. No incoming webhook or event subscription is required for this automation. If a simplified setup is preferred, an incoming webhook URL scoped to a specific channel can be used instead and stored as SLACK_WEBHOOK_URL.
Required configuration
Store a mapping of HubSpot owner ID to Slack user ID in the credential or configuration store as a JSON object (SLACK_USER_MAP). This is used by Agent 3 to direct the alert to the correct rep. Define the alert message Block Kit template in the configuration store, not inline in the workflow. The template must include: lead full name, company, reply excerpt (first 200 characters), and a button linking to the HubSpot contact record URL.
Rate limits
Slack Web API enforces a Tier 3 rate limit of approximately 50 requests per minute for chat.postMessage. At 40 to 80 warm reply alerts per month, peak load is well under 1 request per minute. No throttling is needed.
Constraints
The bot must be invited to any private channel before it can post. Slack bot tokens do not expire but are invalidated if the app is uninstalled. The orchestration layer must handle a Slack API error response (non-ok field in the response JSON) and log the failure to the Google Sheets audit log rather than dropping the alert silently.
Google Sheets

Audit log and sequence tracker. Agent 1 writes one row per triggered lead at the start of each workflow run. Subsequent agents append status updates to the same row.

Auth method
OAuth 2.0 via a Google service account. Create a service account in Google Cloud Console, download the JSON key, and store the entire key JSON as GOOGLE_SERVICE_ACCOUNT_JSON in the credential store. Share the target spreadsheet with the service account email address (editor access).
Required scopes
https://www.googleapis.com/auth/spreadsheets, https://www.googleapis.com/auth/drive.file
Webhook / trigger setup
No webhook. All reads and writes use the Google Sheets API v4 (spreadsheets.values.append and spreadsheets.values.update). The orchestration layer references the spreadsheet by its ID stored in the credential store as SHEETS_AUDIT_LOG_ID.
Required configuration
The audit log spreadsheet must have the following column headers in row 1: contact_id, contact_email, contact_name, hubspot_owner_id, trigger_date, sequence_step, email_sent_at, reply_received, reply_intent, final_status. Store the spreadsheet ID as SHEETS_AUDIT_LOG_ID and the target sheet tab name as SHEETS_TAB_NAME in the credential store. Do not hardcode either value in workflow nodes.
Rate limits
Google Sheets API enforces 300 read requests per minute per project and 300 write requests per minute per project. At 40 to 80 leads per month and three touches per lead, maximum write operations are under 30 per day. No throttling is required.
Constraints
Service account keys must be rotated at least every 90 days. The orchestration layer must handle a 429 response with exponential backoff before retrying. Writes to the audit log must never block the primary email send flow; if the Sheets write fails, log the error to the orchestration platform's internal error log and continue.
Integration and API SpecPage 1 of 3
FS-DOC-05Technical

03Field mappings between tools

The following tables define the exact field-level mappings for each agent handoff in the automation. Field names are shown in monospace format as they appear in the respective tool's API response or payload schema. All intermediate values are passed as named variables in the orchestration layer's run context.

Handoff 1: Agent 1 (Lead Inactivity Monitor) to Agent 2 (Sequence Copywriter Agent)

Source tool
Source field
Destination tool
Destination field
HubSpot Contacts API
`properties.hs_object_id`
Orchestration context
`contact_id`
HubSpot Contacts API
`properties.email`
Orchestration context
`contact_email`
HubSpot Contacts API
`properties.firstname`
Orchestration context
`contact_first_name`
HubSpot Contacts API
`properties.lastname`
Orchestration context
`contact_last_name`
HubSpot Contacts API
`properties.company`
Orchestration context
`contact_company`
HubSpot Contacts API
`properties.hubspot_owner_id`
Orchestration context
`hubspot_owner_id`
HubSpot Contacts API
`properties.hs_last_sales_activity_timestamp`
Orchestration context
`last_activity_date`
HubSpot Contacts API
`properties.re_engagement_sequence_step`
Orchestration context
`current_sequence_step`
HubSpot Deals API
`properties.dealname`
Orchestration context
`deal_name`
HubSpot Deals API
`properties.dealstage`
Orchestration context
`deal_stage`
HubSpot Engagements API
`engagement.metadata.body` (most recent note)
Orchestration context
`last_interaction_note`
Google Sheets
`contact_id` (row lookup)
Orchestration context
`audit_row_index`

Handoff 2: Agent 2 (Sequence Copywriter Agent) to Gmail and HubSpot

Source tool
Source field
Destination tool
Destination field
Orchestration context
`contact_email`
Gmail API
`to` (message header)
Orchestration context
`hubspot_owner_id` -> resolved rep email
Gmail API
`from` (authenticated account)
OpenAI response
`choices[0].message.content` (subject line extracted)
Gmail API
`subject` (message header)
OpenAI response
`choices[0].message.content` (body extracted)
Gmail API
`body` (HTML or plain text part)
Gmail API response
`id` (message ID)
HubSpot Engagements API
`engagement.metadata.messageId`
Gmail API response
`threadId`
Orchestration context
`gmail_thread_id`
Orchestration context
`contact_id`
HubSpot Contacts API
`properties.re_engagement_sequence_step` (incremented)
Orchestration context
ISO 8601 timestamp (now)
HubSpot Contacts API
`properties.re_engagement_last_sent_date`
Orchestration context
`contact_id`
Google Sheets
`contact_id` column (row update)
Orchestration context
`current_sequence_step` + 1
Google Sheets
`sequence_step` column
Orchestration context
ISO 8601 timestamp (now)
Google Sheets
`email_sent_at` column

Handoff 3: Agent 3 (Reply Classifier and Router) to HubSpot and Slack

Source tool
Source field
Destination tool
Destination field
Gmail Pub/Sub notification
`message.data` (base64 decoded -> `historyId`)
Gmail API
`users.history.list` request parameter
Gmail API
`messages[].id`
Gmail API
`messages.get` request (full payload)
Gmail API
`payload.headers[From].value`
Orchestration context
`reply_from_email`
Gmail API
`threadId`
Orchestration context
`matched_thread_id` (lookup against tracked threads)
OpenAI response
`choices[0].message.content` parsed as JSON -> `intent`
Orchestration context
`reply_intent`
Gmail API
`snippet`
Orchestration context
`reply_excerpt` (truncated to 200 chars)
Orchestration context
`reply_intent` = interested
Slack API
`chat.postMessage` triggered
Orchestration context
`contact_first_name` + `contact_last_name`
Slack Block Kit
`text` field in section block
Orchestration context
`reply_excerpt`
Slack Block Kit
`text` field in context block
Orchestration context
`contact_id` -> HubSpot record URL
Slack Block Kit
`url` field in button element
Orchestration context
`reply_intent` = unsubscribe OR sequence complete
HubSpot Contacts API
`properties.lifecyclestage` = `closedlost`
Orchestration context
`reply_intent`
Google Sheets
`reply_intent` column (row update)
Orchestration context
resolved final status
Google Sheets
`final_status` column (row update)
Integration and API SpecPage 2 of 3
FS-DOC-05Technical

04Build stack and orchestration

Orchestration layout
Three discrete workflows, one per agent. Each workflow is independently triggerable and versioned. Shared state between agents is passed via the orchestration run context (in-memory variables scoped to each run) and persisted to the Google Sheets audit log for cross-run lookups. All credentials are resolved from the centralised credential store at workflow startup; no secrets are embedded in node configuration.
Workflow 1 trigger (Lead Inactivity Monitor)
Scheduled poll. Executes daily at 07:00 AM in the workspace timezone. On each run, issues a POST to the HubSpot Contacts Search API with the inactivity filter. Each matching contact record spawns a child run of Workflow 2. The poll interval is not adjustable below 15 minutes if switched to a shorter cadence in future; no webhook is available from HubSpot for this filter condition.
Workflow 2 trigger (Sequence Copywriter Agent)
Event-driven, triggered by Workflow 1 passing a contact_id payload. Also triggered on scheduled follow-up dates by a time-delay node that fires when re_engagement_last_sent_date plus the configured interval (5 days for touch 2, 7 days for touch 3) is reached. If no reply has been received (checked via audit log lookup), the workflow proceeds; otherwise it exits cleanly.
Workflow 3 trigger (Reply Classifier and Router)
Webhook-driven. Google Cloud Pub/Sub delivers a push notification to the orchestration layer's inbound HTTPS endpoint when Gmail detects a new message. The endpoint validates the Google-signed JWT in the Authorization header before processing. The watch subscription renewal sub-workflow runs every 6 days to ensure continuous coverage. Signature validation must be enforced; unsigned requests must be rejected with a 401 response and logged.
Credential store structure
All secrets are stored in the orchestration platform's built-in encrypted credential vault. See code block below for the full inventory of credential keys.
Environment separation
Maintain separate credential store entries for sandbox and production environments. Prefix sandbox keys with SANDBOX_ during testing. Switch to production credentials only after all test cases in the QA plan have passed.
Credential store inventory. All keys resolved at workflow runtime. Never reference raw values in node configuration.
// Credential store contents (all values stored as encrypted secrets)
// HubSpot
HUBSPOT_API_TOKEN            // Private App bearer token
HUBSPOT_PORTAL_ID            // HubSpot account portal ID (numeric)
HUBSPOT_PIPELINE_ID          // Default deal pipeline ID
HUBSPOT_CLOSEDLOST_STAGE_ID  // Pipeline stage ID for Closed Lost

// Gmail (one entry per rep; {REP_ID} is the HubSpot owner ID)
GMAIL_OAUTH_CLIENT_ID        // Google Cloud OAuth 2.0 client ID
GMAIL_OAUTH_CLIENT_SECRET    // Google Cloud OAuth 2.0 client secret
GMAIL_REFRESH_TOKEN_{REP_ID} // Per-rep refresh token (one per authorised account)
GMAIL_PUBSUB_TOPIC           // Google Cloud Pub/Sub topic name for inbox push
GMAIL_TRACKED_LABEL_ID       // Gmail label ID for 're-engagement-tracked'

// OpenAI
OPENAI_API_KEY               // Organisation-level API key
OPENAI_MODEL                 // e.g. gpt-4o
OPENAI_DRAFT_TEMPERATURE     // Float, e.g. 0.7
OPENAI_SCORE_TEMPERATURE     // Float, e.g. 0.2
OPENAI_MAX_TOKENS_DRAFT      // Integer, e.g. 600
OPENAI_MAX_TOKENS_SCORE      // Integer, e.g. 100

// Slack
SLACK_BOT_TOKEN              // OAuth bot token (xoxb-...)
SLACK_USER_MAP               // JSON object: { "<hubspot_owner_id>": "<slack_user_id>" }
SLACK_FALLBACK_CHANNEL_ID    // Channel ID for unroutable alerts

// Google Sheets
GOOGLE_SERVICE_ACCOUNT_JSON  // Full service account key JSON (stringified)
SHEETS_AUDIT_LOG_ID          // Spreadsheet ID of the audit log workbook
SHEETS_TAB_NAME              // Sheet tab name, e.g. 're-engagement-log'

// Prompt templates (stored as configuration strings, not code)
PROMPT_EMAIL_TOUCH_1         // System + user prompt template for first touch email
PROMPT_EMAIL_TOUCH_2         // System + user prompt template for second touch email
PROMPT_EMAIL_TOUCH_3         // System + user prompt template for third touch email
PROMPT_REPLY_CLASSIFIER      // System + user prompt template for intent scoring

// Orchestration
SEQUENCE_INTERVAL_TOUCH_2    // Integer days between touch 1 and touch 2, e.g. 5
SEQUENCE_INTERVAL_TOUCH_3    // Integer days between touch 2 and touch 3, e.g. 7
INACTIVITY_THRESHOLD_DAYS    // Integer, e.g. 21

05Error handling and retry logic

Every integration point has a defined failure behaviour. Unhandled exceptions must never fail silently. All errors must be logged to the orchestration platform's internal error log and, where appropriate, to the Google Sheets audit log. Retries use exponential backoff unless otherwise stated.

Integration
Scenario
Required behaviour
HubSpot Contacts Search API
HTTP 429 rate limit response during daily scan
Pause execution for 10 seconds and retry up to 3 times with doubling backoff (10s, 20s, 40s). If all retries fail, log the error with timestamp and notify the SLACK_FALLBACK_CHANNEL_ID. Skip the current run; do not re-trigger manually.
HubSpot Contacts Search API
HTTP 500 or 503 response (HubSpot service outage)
Retry 3 times with 60-second intervals. If all fail, abort the daily scan run, log to orchestration error log, and post an alert to SLACK_FALLBACK_CHANNEL_ID. The next scheduled run will attempt again the following day.
HubSpot Contacts Write API
Write to re_engagement_sequence_step or lifecyclestage fails
Retry up to 3 times with 15-second backoff. If the write still fails after retries, log the contact_id and intended write value to the Google Sheets audit log under a dedicated error_log tab. Do not silently proceed without recording the failure.
Gmail OAuth
Access token refresh returns 401 (revoked or expired refresh token)
Immediately halt email sending for that rep account. Post an alert to SLACK_FALLBACK_CHANNEL_ID specifying the affected rep by name (resolved from SLACK_USER_MAP). Do not attempt to send from a different account. Require manual re-authorisation before resuming.
Gmail Send API
HTTP 403 (daily sending limit reached for rep account)
Stop sending for that account for the remainder of the calendar day. Queue unsent leads in the audit log with status pending_send. Resume sends at 07:00 AM the following day. Alert SLACK_FALLBACK_CHANNEL_ID with the count of queued leads.
Gmail Pub/Sub push
Inbound webhook receives a request with an invalid or missing Google-signed JWT
Reject the request with an HTTP 401 response. Log the source IP and timestamp. Do not process the notification payload. This must be enforced at the webhook handler layer before any workflow logic executes.
Gmail watch subscription
Subscription expires (watch TTL of 7 days exceeded without renewal)
The renewal sub-workflow runs every 6 days. If the renewal call fails, retry 3 times with 1-hour intervals. If all fail, alert SLACK_FALLBACK_CHANNEL_ID. In the gap period, no reply notifications will be received; this must be treated as a P1 issue requiring immediate manual resolution.
OpenAI Chat Completions API
Response contains empty choices array or malformed JSON in reply_classifier output
Retry the API call once with identical parameters. If the second call also returns an invalid response, log the contact_id and sequence_step to the error log, set the audit row status to review_required, and halt processing for that lead. Do not send a blank or truncated email.
OpenAI Chat Completions API
HTTP 429 (rate limit or quota exceeded)
Retry after 30 seconds, then 60 seconds, then 120 seconds. If the third retry fails, log and halt the current lead's workflow run. Do not fall through to a template email. Alert SLACK_FALLBACK_CHANNEL_ID if more than 3 leads are queued in error state simultaneously.
Slack chat.postMessage
API returns ok: false (e.g. channel not found, bot not in channel, invalid token)
Log the full Slack API error response and the contact_id to the Google Sheets audit log under the reply_intent column with status slack_send_failed. Attempt to fall back to SLACK_FALLBACK_CHANNEL_ID. If the fallback also fails, the alert is recorded in the audit log only. Must not fail silently.
Google Sheets API
HTTP 429 (quota exceeded) or 503 during audit log write
Retry up to 3 times with 10-second backoff. If all retries fail, write the pending log entry to the orchestration platform's internal error log in JSON format for manual back-fill. The primary workflow (email send or CRM update) must not be blocked waiting for the Sheets write.
Orchestration layer (any agent)
Unhandled exception or uncaught runtime error in any workflow node
The orchestration platform's global error handler must catch the exception, log the full stack trace with the affected contact_id and workflow node name, set the audit log row status to unhandled_error, and post an alert to SLACK_FALLBACK_CHANNEL_ID. No exception may propagate without being caught and recorded.
All error states that update the Google Sheets audit log must write to a dedicated columns: error_code and error_detail. These columns must be present in the spreadsheet from day one of the build. The FullSpec team will validate error logging behaviour as part of the QA test suite before go-live. Contact support@gofullspec.com for any credential provisioning questions or integration blockers during build.
Integration and API SpecPage 3 of 3

More documents for this process

Every document generated for Lost Lead Re-engagement.

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