Back to Client Reporting & Status Updates

Integration and API Spec

The reference during the build: every tool connection, field mapping, error scenario, and change-control rule.

4 pagesPDF · Technical
FS-DOC-05Technical

Integration and API Spec

Client Reporting & Status Updates

Document code
FS-DOC-05
Process
Client Reporting & Status Updates
Audience
Developer
Date
[Today's Date]
Company
[YourCompany.com]
Orchestration layer
FullSpec Automation (n8n-compatible)

01Tool inventory

Tool
Role in process
Auth method
Min plan required
Used by agent
FullSpec Automation
Orchestration, scheduling, monitoring
API key (internal)
Standard ($149/month)
All agents
Asana
Project status source: tasks, blockers, milestones
OAuth 2.0 (PKCE flow)
Free tier (API access included)
Status Gathering Agent
Google Docs
Update drafting: create and populate document from template
OAuth 2.0 (service account or user consent)
Google Workspace Free / personal Google account
Update Drafting Agent
Gmail
Send approved client update email
OAuth 2.0 (Google Identity)
Google Workspace or Gmail (SMTP via OAuth)
Send & Log Agent
HubSpot
Log sent update against CRM contact and deal
Private app token (Bearer)
Free CRM (Engagements API included)
Send & Log Agent
All OAuth tokens must be stored in the orchestration credential store. No plaintext secrets in workflow nodes. Rotate tokens on a 90-day cycle minimum.

02Per-tool integration detail

Asana

Queried by the Status Gathering Agent on the weekly schedule trigger. The integration reads project tasks, sections, and custom fields to build a structured status object per account.

Auth method
OAuth 2.0, authorization code with PKCE. Redirect URI registered in Asana developer console.
Scopes required
default (covers tasks:read, projects:read, workspaces:read, users:read)
Base URL
https://app.asana.com/api/1.0
Key endpoints
GET /projects/{project_gid}/tasks?opt_fields=name,completed,due_on,assignee,custom_fields,notes; GET /tasks/{task_gid}/stories
Rate limits
1,500 requests/minute per OAuth token. Enforce a 50ms delay between paginated calls. 429 responses trigger exponential backoff (see Section 05).
Pagination
Cursor-based via 'offset' param. Follow 'next_page.offset' until null.
Constraints
Free plan: API access included but webhook event volume capped at 300 events/project/hour. Custom fields must be pre-defined in Asana; field GIDs must be stored in config. Guest user tokens cannot read private projects.
Config vars
ASANA_CLIENT_ID, ASANA_CLIENT_SECRET, ASANA_WORKSPACE_GID, ASANA_PROJECT_GID_MAP (JSON: account_id to project_gid)
// Input
account_id: string        // internal account identifier
project_gid: string       // resolved from ASANA_PROJECT_GID_MAP
reporting_week: ISO8601   // e.g. 2024-06-03
// Output
{ account_id, project_name, completed_tasks[], blocked_tasks[],
  upcoming_tasks[], last_updated, raw_notes: string }
Google Docs

Used by the Update Drafting Agent to create a new document from a stored template, populate it with the structured status object, and return a shareable document URL for human review.

Auth method
OAuth 2.0 via Google Identity. Use a service account with domain-wide delegation for unattended server-side writes, or user-consent flow for personal Google accounts.
Scopes required
https://www.googleapis.com/auth/drive.file (create/modify files created by app); https://www.googleapis.com/auth/documents (read/write document content)
Base URL
https://docs.googleapis.com/v1 (Docs API); https://www.googleapis.com/drive/v3 (Drive API for copy/share)
Key endpoints
POST /drive/v3/files/{templateDocId}/copy (create draft); POST /docs/v1/documents/{documentId}:batchUpdate (insert text); PATCH /drive/v3/files/{documentId} (set permissions for reviewer)
Rate limits
Docs API: 300 write requests/minute/user; Drive API: 1,000 requests/100 seconds/user. Batch all text insertions into a single batchUpdate call per document.
Template requirement
A master Google Doc template must be created and its document ID stored as GDOCS_TEMPLATE_ID. Template uses named placeholders: {{account_name}}, {{report_week}}, {{completed_summary}}, {{blockers_summary}}, {{upcoming_summary}}.
Constraints
Service account must have Editor access to the template file. Output documents are created in the service account's Drive unless a target folder ID is specified via GDOCS_OUTPUT_FOLDER_ID. Document sharing link is set to 'anyone with link can comment' for review step.
Config vars
GDOCS_TEMPLATE_ID, GDOCS_OUTPUT_FOLDER_ID, GOOGLE_SA_KEY_JSON (service account), GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
// Input
account_id: string
account_name: string
report_week: string       // e.g. 'Week of 3 Jun 2024'
completed_summary: string
blockers_summary: string
upcoming_summary: string
// Output
{ document_id: string, document_url: string, review_link: string }
Gmail

Used by the Send & Log Agent to send the approved client update email from the account manager's address after the human review gate is passed.

Auth method
OAuth 2.0 via Google Identity. Requires send-as permission for the account manager's mailbox if sending on their behalf (use Gmail API, not SMTP).
Scopes required
https://www.googleapis.com/auth/gmail.send; https://www.googleapis.com/auth/gmail.compose (optional, if saving draft first)
Base URL
https://gmail.googleapis.com/gmail/v1/users/{userId}
Key endpoints
POST /messages/send (send RFC 2822 base64url-encoded message); POST /messages (create draft, optional)
Rate limits
250 quota units/second/user; sending limit 2,000 messages/day (Workspace). At ~40 updates/month this is well within limits. No throttling required.
Message format
RFC 2822 MIME, base64url-encoded. Subject line template: 'Your [AccountName] Update: [ReportWeek]'. Body is plain text with optional HTML part mirroring the Google Doc content.
Constraints
The authenticated user must have 'Send As' delegation enabled for the target mailbox in Google Workspace Admin if the automation sends on behalf of the account manager. Personal Gmail accounts do not support delegation.
Config vars
GMAIL_USER_ID (typically 'me' or email address), GMAIL_SEND_AS_ADDRESS, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
// Input
to_email: string          // client contact email
from_address: string      // account manager send-as address
subject: string
body_plain: string
body_html: string         // optional
document_url: string      // linked in email footer
// Output
{ message_id: string, thread_id: string, sent_at: ISO8601 }
HubSpot

Used by the Send & Log Agent to create a CRM engagement (note or email log) against the relevant contact and deal record immediately after the email is sent.

Auth method
Private app token (Bearer). Create a private app in HubSpot Settings > Integrations > Private Apps. Token is scoped at creation and stored as HUBSPOT_PRIVATE_APP_TOKEN.
Scopes required
crm.objects.contacts.read; crm.objects.contacts.write; crm.objects.deals.read; crm.objects.deals.write; crm.objects.notes.write; crm.objects.engagements.write
Base URL
https://api.hubapi.com
Key endpoints
POST /crm/v3/objects/notes (create note log); POST /crm/v3/associations/note/contacts/batch/create (associate note to contact); GET /crm/v3/objects/contacts/search (look up contact by email); GET /crm/v3/objects/deals/search (look up open deal by contact)
Rate limits
100 requests/10 seconds (burst); 150,000 requests/day. At ~40 logs/month, no throttling required. Still implement 429 retry logic per Section 05.
Note body format
Plain text, max 65,536 characters. Include: 'Client update sent [date]. Report week: [week]. Document: [url]. Sent by: [am_name].'
Constraints
Contact must exist in HubSpot before log is created. If no contact is found by email lookup, the workflow must pause and alert the account manager. Deal association is best-effort: log is created even if no open deal is found.
Config vars
HUBSPOT_PRIVATE_APP_TOKEN, HUBSPOT_PORTAL_ID, HUBSPOT_DEFAULT_OWNER_ID
// Input
contact_email: string
account_name: string
report_week: string
document_url: string
sent_at: ISO8601
gmail_message_id: string
am_name: string
// Output
{ note_id: string, contact_id: string, deal_id: string|null,
  logged_at: ISO8601 }
Integration and API SpecPage 1 of 3
FS-DOC-05Technical

03Field mappings between tools

Three agent handoffs occur in this pipeline: (1) Asana to Status Gathering Agent output, (2) Status Gathering Agent output to Google Docs (Update Drafting Agent), (3) Google Docs output plus Gmail to HubSpot (Send & Log Agent). One mapping table per handoff follows.

Handoff 1: Asana to Status Gathering Agent structured output

Source tool
Source field (Asana API)
Destination field (agent payload)
Type
Transform / notes
Asana
project.name
project_name
string
Direct map
Asana
task.name
completed_tasks[].name
string
Filter: task.completed = true
Asana
task.completed_at
completed_tasks[].completed_at
ISO8601
Direct map
Asana
task.name
blocked_tasks[].name
string
Filter: custom_field 'status' = 'Blocked'
Asana
task.notes
blocked_tasks[].blocker_note
string
Truncate to 500 chars
Asana
task.name
upcoming_tasks[].name
string
Filter: due_on within next 7 days, not complete
Asana
task.due_on
upcoming_tasks[].due_on
date string
Format: D MMM YYYY
Asana
task.assignee.name
upcoming_tasks[].assignee
string
Direct map
Config
ASANA_PROJECT_GID_MAP[account_id]
account_id
string
Injected by orchestration at trigger time

Handoff 2: Status Gathering Agent output to Google Docs (Update Drafting Agent)

Source field (agent payload)
Destination placeholder (Google Doc template)
Type
Transform / notes
account_name
{{account_name}}
string
Direct substitution
reporting_week
{{report_week}}
string
Format: 'Week of D MMM YYYY'
completed_tasks[]
{{completed_summary}}
string (rendered list)
Join task names as bulleted plain-text list; max 10 items
blocked_tasks[]
{{blockers_summary}}
string (rendered list)
If empty, substitute 'No blockers this week.'
upcoming_tasks[]
{{upcoming_summary}}
string (rendered list)
Include due date and assignee per item
account_id
Not written to document
string
Carried as metadata for downstream handoff only

Handoff 3: Google Docs and Gmail output to HubSpot (Send & Log Agent)

Source tool
Source field
Destination field (HubSpot note body / association)
Type
Transform / notes
Gmail
message.sent_at
note.timestamp
ISO8601 epoch ms
Convert ISO8601 to Unix ms for HubSpot hs_timestamp
Gmail
message.to_email
contact lookup: email
string
Used in /contacts/search filter
Gmail
message.subject
note.hs_note_body (line 1)
string
Prepend 'Subject: '
Gmail
message.message_id
note.hs_note_body (line 2)
string
Prepend 'Gmail message ID: '
Google Docs
document_url
note.hs_note_body (line 3)
string (URL)
Prepend 'Report document: '
Agent payload
am_name
note.hs_note_body (line 4)
string
Prepend 'Sent by: '
Agent payload
report_week
note.hs_note_body (line 5)
string
Prepend 'Report week: '
HubSpot lookup
contact.id
association: note to contact
string
POST /associations/note/contacts/batch/create
HubSpot lookup
deal.id (if found)
association: note to deal
string
Best-effort; skip if null

04Build stack and orchestration

Layer
Technology
Version / spec
Purpose
Notes
Orchestration
FullSpec Automation (n8n-compatible)
n8n >= 1.30
Workflow scheduling, agent chaining, error capture
Self-hosted or FullSpec cloud
Trigger
n8n Schedule Trigger node
Cron: 0 8 * * 1 (Monday 08:00)
Fire weekly per account
One workflow instance per account or loop over account list
HTTP client
n8n HTTP Request node
Native
Asana API, HubSpot API calls
Set header 'Accept: application/json' on all requests
Google auth
n8n Google OAuth2 credential
OAuth 2.0
Shared across Docs and Gmail nodes
Single credential works for both if scopes combined
Data transform
n8n Code node (JavaScript)
Node.js 18
Filter tasks, format strings, build MIME message
Keep functions pure; log inputs and outputs
Human gate
n8n Wait node + Email/Slack notify
Native
Pause workflow pending AM approval
Timeout: 24 hrs; on timeout escalate to Delivery Lead
Logging
n8n execution log + HubSpot note
Native
Audit trail per run
Retain n8n execution history for 90 days minimum
Secrets
n8n credential store (encrypted)
AES-256 at rest
All API keys and OAuth tokens
Never use Set node to store secrets as plain values
Environment
Production / Staging
Two n8n environments
Isolate test runs from live sends
Staging uses a test HubSpot sandbox and Asana test project

n8n credential store entries required. Each entry name below maps exactly to the credential name referenced in workflow nodes.

All values in {{ }} must be populated before first execution. Store in n8n credential manager, never in workflow JSON.
// n8n Credential Store -- required entries

// 1. Asana OAuth2
Credential name : Asana OAuth2
Type            : OAuth2
Client ID       : {{ ASANA_CLIENT_ID }}
Client Secret   : {{ ASANA_CLIENT_SECRET }}
Auth URL        : https://app.asana.com/-/oauth_authorize
Token URL       : https://app.asana.com/-/oauth_token
Scope           : default
PKCE            : enabled

// 2. Google OAuth2 (Docs + Gmail combined)
Credential name : Google OAuth2 -- Reporting
Type            : OAuth2
Client ID       : {{ GOOGLE_CLIENT_ID }}
Client Secret   : {{ GOOGLE_CLIENT_SECRET }}
Auth URL        : https://accounts.google.com/o/oauth2/v2/auth
Token URL       : https://oauth2.googleapis.com/token
Scopes          : https://www.googleapis.com/auth/drive.file
                  https://www.googleapis.com/auth/documents
                  https://www.googleapis.com/auth/gmail.send
                  https://www.googleapis.com/auth/gmail.compose

// 3. HubSpot Private App
Credential name : HubSpot Private App -- Reporting
Type            : Header Auth
Header name     : Authorization
Header value    : Bearer {{ HUBSPOT_PRIVATE_APP_TOKEN }}

// 4. FullSpec Automation internal
Credential name : FullSpec Internal API
Type            : Header Auth
Header name     : x-fs-api-key
Header value    : {{ FULLSPEC_API_KEY }}

// 5. Environment config (stored as n8n env vars)
ASANA_WORKSPACE_GID       = <workspace_gid>
ASANA_PROJECT_GID_MAP     = '{"acc_001":"12345","acc_002":"67890"}'
GDOCS_TEMPLATE_ID         = <template_doc_id>
GDOCS_OUTPUT_FOLDER_ID    = <drive_folder_id>
GMAIL_SEND_AS_ADDRESS     = am@yourcompany.com
HUBSPOT_PORTAL_ID         = <portal_id>
HUBSPOT_DEFAULT_OWNER_ID  = <owner_id>
Integration and API SpecPage 2 of 3
FS-DOC-05Technical

05Error handling and retry logic

Error scenario
HTTP / error code
Affected node
Retry strategy
Escalation action
Asana token expired
401 Unauthorized
HTTP Request: Asana task fetch
n8n OAuth2 auto-refresh on 401; retry once after refresh
Alert developer if refresh fails; halt workflow
Asana rate limit exceeded
429 Too Many Requests
HTTP Request: Asana pagination loop
Exponential backoff: 1s, 2s, 4s, 8s (max 4 retries)
Log and skip account if max retries reached; alert AM
Asana project GID not found in config map
n/a (config error)
Code node: resolve project GID
No retry; fail fast
Halt workflow; send config error alert to developer
Google OAuth2 token expired
401 Unauthorized
Google Docs / Gmail node
n8n OAuth2 auto-refresh on 401; retry once
Alert developer if refresh fails; halt workflow
Google Docs template copy fails
403 Forbidden / 404 Not Found
HTTP Request: Drive copy template
No retry on 403 (permission issue); 1 retry on 404
Alert developer; verify GDOCS_TEMPLATE_ID and service account access
Google Docs batchUpdate write fails
400 Bad Request
HTTP Request: Docs batchUpdate
1 retry with cleaned payload (strip unsupported chars)
Log raw payload; alert developer if second attempt fails
Gmail send fails: daily quota exceeded
429 / 403 rateLimitExceeded
Gmail send node
No retry same day; reschedule to next available slot
Alert AM; do not lose draft. Store unsent message ID.
Gmail send fails: invalid recipient address
400 invalidArgument
Gmail send node
No retry
Halt send step; alert AM to verify client email in HubSpot
HubSpot contact not found by email
200 empty results
HTTP Request: HubSpot contact search
No retry; contact does not exist
Create a HubSpot task assigned to AM to add contact; continue email send
HubSpot note creation fails
400 / 429
HTTP Request: HubSpot POST note
3 retries with 2s delay on 429; no retry on 400
Log failure with gmail_message_id; alert AM to log manually
Human review gate timeout (24 hrs)
n/a (Wait node timeout)
n8n Wait node
No retry; workflow resumes on timeout path
Escalate draft to Delivery Lead via email notification; do not auto-send
Orchestration node execution error (unhandled exception)
n8n internal error
Any Code node
Catch in try/catch; log error object; 1 retry
Send full error payload to developer alert channel; halt workflow run
All retry attempts must be logged to the n8n execution history with timestamp, error code, and attempt number. Failed runs must never silently drop. The minimum alerting channel is email to the developer and the account manager owner for that workflow instance.

06Versioning and change control

Item
Convention / policy
Detail
Workflow version format
MAJOR.MINOR.PATCH
MAJOR: breaking change to agent logic or data schema; MINOR: new field mapping or added tool; PATCH: bug fix or config update
Initial release version
1.0.0
Baseline release covering all three agents and four tool integrations
Version tag location
n8n workflow description field
Format: 'v1.0.0 | [Date] | [Author initials] | [Short change summary]'
Workflow export and backup
JSON export on every MINOR+ change
Exported JSON committed to version-controlled repository (Git). Branch naming: automation/client-reporting/v[version]
Credential rotation
90-day cycle
Asana and Google OAuth tokens refreshed automatically; HubSpot private app token manually rotated. Calendar reminder set in advance.
Schema change process
Change request required for MAJOR bumps
Any change to field names in Section 03 tables requires a written change request, re-test of affected agents, and sign-off from the process owner before deployment
Staging gate
All changes deploy to staging first
A full end-to-end test run must pass in the staging environment (test project, sandbox CRM) before promotion to production
Rollback procedure
Revert to previous JSON export
Import prior workflow JSON version in n8n; reactivate. Maximum rollback time: 15 minutes. Prior credential entries are retained.
Dependency tracking
Tracked in a tool-version register
Record the Asana API version (v1.0), Google APIs (v1), HubSpot API (v3) in the register. Review on each MINOR+ change for deprecation notices.
Change log
Maintained in workflow description and repository CHANGELOG.md
Each entry: version, date, author, change type (add/modify/fix/remove), brief description, linked test run ID
API versions referenced in this document: Asana REST API v1.0; Google Docs API v1; Google Drive API v3; Gmail API v1; HubSpot CRM API v3. Monitor each provider's deprecation notices quarterly and update the dependency register accordingly.
Integration and API SpecPage 3 of 3

More documents for this process

Every document generated for Client Reporting & Status Updates.

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