Back to Contract Generation & E-sign

Developer Handover Pack

Everything needed to build the automation from scratch: current state, full agent specs, data flow, and the build stack.

4 pagesPDF · Technical
FS-DOC-04Technical

Developer Handover Pack

Contract Generation & E-sign

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

This document provides the complete technical specification for the Contract Generation and E-sign automation. It is intended for the FullSpec build team and covers the current-state process map, agent specifications with IO contracts, the end-to-end data flow, and the recommended build stack. Everything a developer needs to begin implementation without further discovery is contained here. The process owner and sales ops lead are responsible for confirming template field mappings and HubSpot deal property completeness before build begins.

01Process snapshot

Step
Name
Description
1
Confirm Deal Closed in CRM
Sales rep marks the deal as Closed Won in HubSpot and verifies all deal fields are complete before generating the contract. (5 min)
2
Select Correct Contract Template
Rep opens Google Drive and manually identifies the right template based on deal type, product line, or customer region. BOTTLENECK. (8 min)
3
Copy Deal Data Into Document
Rep manually copies customer name, address, pricing, payment terms, and scope from HubSpot into the template document. BOTTLENECK. (20 min)
4
Internal Review of Contract
Sales manager or ops lead reviews the draft contract to confirm figures and terms are correct before it leaves the building. (10 min)
5
Export to PDF and Upload to DocuSign
Rep exports the approved document as a PDF and uploads it to DocuSign, placing signature and date fields manually. (10 min)
6
Send Contract to Customer via Email
Rep composes a cover email in Gmail and sends the DocuSign envelope link to the customer contact. (7 min)
7
Chase Unsigned Contracts Manually
Rep sends a manual follow-up email if the customer has not signed within a few days. No system reminder exists. BOTTLENECK. (15 min)
8
Download Signed Document
Once the customer signs, the rep downloads the completed PDF from DocuSign and saves it to the relevant Google Drive folder. (5 min)
9
Attach Signed Contract to CRM Deal
Rep manually attaches the signed PDF to the HubSpot deal record and updates the deal stage or contract status property. (5 min)
10
Notify Finance and Delivery Teams
Rep or ops lead sends a Slack message to let finance and the delivery team know the contract is signed and work can begin. (5 min)
Time cost summary: Total manual time per contract cycle is 90 minutes. At approximately 60 contracts per month this equates to roughly 90 hours of manual work per month and 5 hours of manual work per week at the team level. The automation replaces steps 2, 3 (Contract Assembly Agent), steps 7, 8 (Signature Tracking and Follow-up Agent), and steps 9, 10 (Post-Signature CRM and Notification Agent). Steps 1 and 4 remain as appropriate human-in-the-loop gates.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Contract Assembly Agent

Triggered the moment a HubSpot deal transitions to Closed Won, this agent reads all relevant deal properties from the HubSpot Deals API, evaluates a template selection ruleset stored in the automation platform to identify the correct contract template in Google Drive, and performs a field merge to produce a fully populated draft document. The agent writes the output file back to a designated output folder in Google Drive and updates a HubSpot deal property (contract_draft_url) with the direct link to the draft, ready for manager review in Slack. No document leaves the organisation at this stage.

Trigger
HubSpot deal stage changes to Closed Won (webhook event: deal.propertyChange, property: dealstage)
Tools
HubSpot, Google Drive
Replaces steps
Step 2 (template selection) and Step 3 (data merge into document)
Estimated build
10 hours — Moderate complexity
// Input
hubspot.deal.id          : string   // HubSpot deal record ID
hubspot.deal.dealname    : string   // Deal or company name
hubspot.deal.amount      : number   // Contract value in USD
hubspot.deal.closedate   : date     // ISO 8601 expected close date
hubspot.deal.deal_type   : string   // Enum: retainer | project | saas | other
hubspot.deal.region      : string   // Enum: us | uk | apac | other
hubspot.contact.email    : string   // Primary contact email address
hubspot.contact.firstname: string
hubspot.contact.lastname : string
hubspot.contact.company  : string
hubspot.deal.payment_terms: string  // e.g. 'Net 30'
hubspot.deal.scope_notes : string   // Free-text scope or deliverables field

// Output
gdrive.draft_file_id     : string   // Google Drive file ID of merged draft
gdrive.draft_url         : string   // Shareable preview link (view-only)
hubspot.contract_draft_url: string  // Written back to deal property
hubspot.contract_status  : string   // Set to 'draft_generated'
slack.review_message_ts  : string   // Timestamp of Slack review prompt (posted by orchestration layer)
  • HubSpot tier requirement: Operations Hub Starter or above is required for webhook triggers on deal stage change. Confirm the account tier with the process owner before build begins.
  • Google Drive template library must be stored in a dedicated service-account-accessible folder. The folder ID is recorded in the automation platform credential store and must not be hardcoded in workflow nodes.
  • Template selection logic is a conditional ruleset keyed on deal_type and region. Up to 10 standard templates are supported; confirm the exact number and naming convention during the template audit (template audit was completed April 10).
  • All merge fields use double-brace notation ({{contact.firstname}}, {{deal.amount}}, etc.) in the Google Drive template files. The template owner must confirm field names match HubSpot property API names exactly before the merge step is built.
  • If any required HubSpot deal property is null or empty at trigger time, the agent must halt and post an error alert to Slack (channel: #contract-errors) rather than producing a partially populated draft. Do not attempt a partial merge.
  • Dedupe: if a Closed Won webhook fires more than once for the same deal ID within 10 minutes (HubSpot can fire duplicate webhooks), the agent must check for an existing draft file linked to that deal ID and skip re-generation.
  • The output Google Drive file must be created as a Google Doc (not an exported PDF) at this stage so the manager can view it in-browser via Slack preview link.
  • Confirm Google Drive API scope required: https://www.googleapis.com/auth/drive (read and write to the designated template and output folders only).
Signature Tracking and Follow-up Agent

This agent activates once the automation platform creates and sends a DocuSign envelope from the approved contract draft. It subscribes to DocuSign Connect webhook events to monitor envelope status in real time. If the envelope status does not advance to 'delivered' (opened) within 48 hours of dispatch, the agent sends a first follow-up email through Gmail using a pre-written template. If the status has not advanced to 'completed' (signed) within 96 hours of the original send, a second follow-up email is sent. The agent passes the final envelope status and completion timestamp downstream to the Post-Signature Agent on receipt of a 'completed' event.

Trigger
DocuSign envelope created and dispatched (DocuSign Connect webhook: envelope-sent event)
Tools
DocuSign, Gmail
Replaces steps
Step 7 (chase unsigned contracts) and Step 8 (download signed document)
Estimated build
8 hours — Moderate complexity
// Input
docusign.envelope_id     : string   // DocuSign envelope GUID
docusign.recipient_email : string   // Signer email address
docusign.recipient_name  : string   // Signer display name
docusign.sent_at         : datetime // ISO 8601 envelope send timestamp
hubspot.deal.id          : string   // Passed forward from Contract Assembly Agent
hubspot.deal.dealname    : string

// Output (on 48h no-open event)
gmail.followup_1_sent_at : datetime // Timestamp of first follow-up email
gmail.followup_1_message_id: string // Gmail message ID for audit

// Output (on 96h no-sign event)
gmail.followup_2_sent_at : datetime // Timestamp of second follow-up email
gmail.followup_2_message_id: string

// On approval (envelope completed)
docusign.envelope_id     : string   // Passed to Post-Signature Agent
docusign.completed_at    : datetime // Signature completion timestamp
docusign.signed_pdf_url  : string   // DocuSign download URI for signed PDF
hubspot.deal.id          : string   // Forwarded for CRM attachment step
  • DocuSign tier requirement: a DocuSign plan that includes Connect (webhook callbacks) is required. The Standard plan ($45/month as confirmed in tooling) includes Connect. Confirm webhook delivery endpoint is publicly accessible and uses HTTPS with a valid TLS certificate.
  • DocuSign Connect must be configured to fire events for: envelope-sent, envelope-delivered, and envelope-completed. The voided and declined events must also be captured and routed to the #contract-errors Slack channel.
  • The 48-hour and 96-hour timers are implemented as delayed branches in the automation platform, not as cron jobs. The timer resets on each check: if the envelope moves to 'delivered' before 48 hours, the first follow-up is suppressed and only the 96-hour unsigned check runs.
  • Gmail send account must be a shared sales mailbox (e.g. contracts@[YourCompany.com]), not a personal rep address, so replies are visible to the team. Confirm OAuth 2.0 access is granted for this mailbox with scope: https://www.googleapis.com/auth/gmail.send.
  • Follow-up email templates (subject lines and body copy) must be approved by the sales ops lead before build. Store them as named text assets in the automation platform, not hardcoded strings.
  • If the envelope is voided or declined by the customer, the agent must halt the follow-up sequence and post an alert to #contract-errors with the envelope ID and reason code. Do not send follow-up emails to a customer who has explicitly declined.
  • Fallback: if DocuSign Connect fails to deliver a webhook within 2 hours of an expected status change, the agent should poll the DocuSign Envelopes:get endpoint as a safety net on a 30-minute interval.
Post-Signature CRM and Notification Agent

Triggered by the DocuSign envelope-completed event passed forward from the Signature Tracking Agent, this agent downloads the signed PDF from DocuSign using the signed document download API, attaches it to the originating HubSpot deal record via the CRM Engagements API, and sets the deal's contract_status property to 'signed'. It then constructs and posts a completion notification to the configured Slack channels (sales, finance, and delivery) confirming the deal name, signing timestamp, and a direct link to the signed document in HubSpot. This agent is the final automated step in the flow.

Trigger
DocuSign envelope status reported as completed (passed from Signature Tracking and Follow-up Agent)
Tools
DocuSign, HubSpot, Slack
Replaces steps
Step 9 (attach signed contract to CRM) and Step 10 (notify finance and delivery teams)
Estimated build
6 hours — Simple complexity
// Input
docusign.envelope_id     : string   // DocuSign envelope GUID
docusign.signed_pdf_url  : string   // Download URI for completed PDF
docusign.completed_at    : datetime // ISO 8601 completion timestamp
hubspot.deal.id          : string   // Target deal record for attachment
hubspot.deal.dealname    : string   // Used in Slack notification text

// Output
hubspot.attachment_id    : string   // HubSpot engagement/note ID for attached file
hubspot.contract_status  : string   // Updated to 'signed'
hubspot.contract_signed_at: datetime // Deal property updated with completion timestamp
slack.sales_message_ts   : string   // Posted message timestamp in #contracts-signed
slack.finance_message_ts : string   // Posted message timestamp in #finance-alerts
slack.delivery_message_ts: string   // Posted message timestamp in #delivery-handoff
  • HubSpot file attachment uses the Files API (v3) to upload the PDF binary, then the Engagements API to associate the file with the deal record. The deal ID must be carried through all prior agent outputs without mutation.
  • The signed PDF should be uploaded to HubSpot with a standardised filename format: [DealName]_SignedContract_[YYYY-MM-DD].pdf. Confirm naming convention with ops lead before build.
  • Slack notifications require a bot token with scopes: chat:write and files:read. The bot must be invited to all three target channels (#contracts-signed, #finance-alerts, #delivery-handoff) before go-live. Confirm channel names with the process owner.
  • If the HubSpot file upload fails (e.g. file size exceeds 25 MB limit or API rate limit hit), the agent must retry once after 60 seconds, then log the failure to the Supabase error table and alert #contract-errors. The signed PDF must never be silently lost.
  • DocuSign signed document download uses the Envelopes:getDocument endpoint with document_id=combined for the merged signed PDF. The agent must use the DocuSign service integration account credentials, not a personal user token.
  • Simple complexity rating assumes the Slack and HubSpot credential connections are already configured in the shared credential store from the Contract Assembly Agent build. Do not re-create connections; reference the existing stored credentials.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow: Contract Generation and E-sign
// ─────────────────────────────────────────────────────────────────────
// TRIGGER: HubSpot deal stage webhook
// ──────────────────────────��──────────────────────────────────────────
EVENT: hubspot.webhook → deal.propertyChange
  property_name : 'dealstage'
  new_value     : 'closedwon'
  deal.id       : '{{deal_id}}'

// Orchestration layer receives webhook, validates deal_id is not duplicate
// within 10-minute deduplication window (checked against run log)

// ─────────────────────────────────────────────────────────────────────
// AGENT 1: Contract Assembly Agent
// ─────────────────────────────────────────────────────────────────────
FETCH: HubSpot Deals API → GET /crm/v3/objects/deals/{{deal_id}}
  fields: dealname, amount, closedate, deal_type, region,
          payment_terms, scope_notes

FETCH: HubSpot Contacts API → GET /crm/v3/objects/contacts
  association: deal_id
  fields: email, firstname, lastname, company

// Null-check: if any required field is null → HALT, post to #contract-errors
VALIDATE: [dealname, amount, closedate, deal_type, email, firstname, lastname]
  on_fail: slack.post(channel='#contract-errors', message='Missing fields on deal {{deal_id}}')
           → terminate workflow

// Template selection ruleset (keyed on deal_type + region)
SELECT: gdrive_template_id = templateRuleset(deal_type, region)
  inputs : deal_type = '{{deal.deal_type}}', region = '{{deal.region}}'
  returns: gdrive_template_id : string  // e.g. '1BxiMV...gdrive_id'

// Copy template to output folder and merge fields
COPY:  Google Drive Files API → POST /drive/v3/files/{{template_id}}/copy
  parent_folder: OUTPUT_FOLDER_ID  // stored in credential store
  new_title    : '{{dealname}}_ContractDraft_{{YYYY-MM-DD}}'

MERGE: Google Drive Docs API → batch update on new_file_id
  {{contact.firstname}}  → deal.contact.firstname
  {{contact.lastname}}   → deal.contact.lastname
  {{contact.company}}    → deal.contact.company
  {{contact.email}}      → deal.contact.email
  {{deal.dealname}}      → deal.dealname
  {{deal.amount}}        → deal.amount (formatted: $#,##0.00)
  {{deal.closedate}}     → deal.closedate (formatted: MMMM DD, YYYY)
  {{deal.payment_terms}} → deal.payment_terms
  {{deal.scope_notes}}   → deal.scope_notes
  {{deal.region}}        → deal.region

// Write draft URL back to HubSpot and post Slack review prompt
UPDATE: HubSpot Deals API → PATCH /crm/v3/objects/deals/{{deal_id}}
  contract_draft_url : gdrive.draft_url
  contract_status    : 'draft_generated'

POST:  Slack → chat.postMessage
  channel : '#contract-review'
  text    : 'Contract draft ready for {{dealname}}. Review: {{gdrive.draft_url}}'
  actions : [{ type: 'button', text: 'Approve', value: 'approved' },
             { type: 'button', text: 'Request Changes', value: 'rejected' }]

// ─────────────────────────────────────────────────────────────────────
// HUMAN GATE: Sales Manager Review in Slack (Step 4 — retained manual step)
// ─────────────────────────────────────────────────────────────────────
WAIT: slack.interactiveCallback
  timeout   : 24h  // if no response, re-post reminder to #contract-review
  on_approve: → proceed to DocuSign envelope creation
  on_reject : → post rejection note to #contract-review, terminate workflow

// ─────────────────────────────────────────────────────────────────────
// DOCUSIGN: Envelope creation and dispatch (orchestration layer action)
// ─────────────────────────────────────────────────────────────────────
EXPORT: Google Drive → export as PDF
  file_id : gdrive.draft_file_id
  mime    : application/pdf

CREATE: DocuSign Envelopes API → POST /v2.1/accounts/{{account_id}}/envelopes
  document  : signed_pdf_binary
  recipient : { email: contact.email, name: contact.firstname + ' ' + contact.lastname,
                routingOrder: 1, recipientType: 'signer' }
  tabs      : { signHere: [{ pageNumber: last, xPosition: 100, yPosition: 200 }],
                dateSigned: [{ pageNumber: last, xPosition: 300, yPosition: 200 }] }
  status    : 'sent'
  returns   : envelope_id, sent_at

// ─────────────────────────────────────────────────────────────────────
// AGENT 2: Signature Tracking and Follow-up Agent
// ─────────────────────────────────────────────────────────────────────
LISTEN: DocuSign Connect webhook → envelope-delivered, envelope-completed,
        envelope-voided, envelope-declined

// 48-hour no-open check
TIMER: delay 48h from sent_at
  CHECK: docusign.envelope_status != 'delivered' AND != 'completed'
  on_true:
    SEND: Gmail → users.messages.send
      from    : contracts@[YourCompany.com]
      to      : contact.email
      subject : 'Your contract from [YourCompany.com] is waiting for your signature'
      body    : followup_template_1 (merge: contact.firstname, deal.dealname)
      returns : followup_1_message_id, followup_1_sent_at

// 96-hour no-sign check
TIMER: delay 96h from sent_at
  CHECK: docusign.envelope_status != 'completed'
  on_true:
    SEND: Gmail → users.messages.send
      from    : contracts@[YourCompany.com]
      to      : contact.email
      subject : 'Quick reminder: your contract from [YourCompany.com]'
      body    : followup_template_2 (merge: contact.firstname, deal.dealname)
      returns : followup_2_message_id, followup_2_sent_at

// On decline or void
ON: envelope-voided OR envelope-declined
  POST: Slack #contract-errors
    text: 'Envelope {{envelope_id}} for {{dealname}} was {{status}}. Reason: {{reason}}'
  → terminate follow-up sequence

// On completion, forward to Agent 3
ON: envelope-completed
  PASS: envelope_id, signed_pdf_url, completed_at, deal.id, deal.dealname

// ─────────────────────────────────────────────────────────────────────
// AGENT 3: Post-Signature CRM and Notification Agent
// ─────────────────────────────────────────────────────────────────────
DOWNLOAD: DocuSign Envelopes API
  GET /v2.1/accounts/{{account_id}}/envelopes/{{envelope_id}}/documents/combined
  returns: signed_pdf_binary

UPLOAD: HubSpot Files API → POST /filemanager/api/v3/files/upload
  file_name  : '{{dealname}}_SignedContract_{{YYYY-MM-DD}}.pdf'
  file_binary: signed_pdf_binary
  returns    : hubspot_file_id, hubspot_file_url

ATTACH: HubSpot Engagements API → POST /engagements/v1/engagements
  type         : 'NOTE'
  associations : { dealIds: [deal.id] }
  metadata     : { body: 'Signed contract attached. Signed at: {{completed_at}}' }
  attachment   : hubspot_file_id

UPDATE: HubSpot Deals API → PATCH /crm/v3/objects/deals/{{deal_id}}
  contract_status     : 'signed'
  contract_signed_at  : completed_at

POST: Slack → chat.postMessage (three channels)
  channels : ['#contracts-signed', '#finance-alerts', '#delivery-handoff']
  text     : 'Contract signed: {{dealname}} | Signed: {{completed_at}}
              | View in HubSpot: {{hubspot_file_url}}'

// ─────────────────────────────────────────────────────────────────────
// END OF FLOW
// ─────────────────────────────────────────────────────────────────────
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation platform configured with one workflow per agent (three workflows total): Contract Assembly, Signature Tracking and Follow-up, and Post-Signature CRM and Notification. All tool credentials (HubSpot API key, Google Drive OAuth token, DocuSign integration key and RSA keypair, Gmail OAuth token, Slack bot token) are stored in a shared credential store and referenced by name, never hardcoded. Workflow-to-workflow handoffs use a shared context object keyed on deal_id.
Webhook configuration
HubSpot deal stage webhook: configured in HubSpot Settings > Integrations > Private Apps > Webhooks, subscribed to deal.propertyChange for property dealstage. Endpoint: POST https://automation.[YourCompany.com]/hooks/hubspot-deal-stage (HTTPS required, shared secret verified in handler). DocuSign Connect: configured in DocuSign Admin > Connect, subscribed to envelope-sent, envelope-delivered, envelope-completed, envelope-voided, envelope-declined. Endpoint: POST https://automation.[YourCompany.com]/hooks/docusign-envelope. Slack interactive callbacks: configured via Slack App > Interactivity and Shortcuts, request URL: POST https://automation.[YourCompany.com]/hooks/slack-actions.
Templating approach
Contract templates are Google Docs stored in a dedicated Google Drive folder (TEMPLATE_FOLDER_ID recorded in the credential store). Merge fields use double-brace syntax (e.g. {{deal.amount}}) matching HubSpot property API names exactly. The template selection ruleset is a JSON lookup table stored as a workflow variable or environment config, mapping deal_type plus region to a template Google Doc ID. Template layout changes require a corresponding update to the DocuSign tab position configuration.
Error logging
All agent errors and failed retries are written to a Supabase table (schema: run_id, workflow_name, deal_id, error_type, error_message, occurred_at, resolved). On any insert to this table, an alert is posted automatically to the Slack channel #contract-errors. Critical errors (null field validation failure, PDF upload failure, DocuSign webhook timeout) trigger an immediate alert. Non-critical warnings (duplicate webhook suppressed, retry succeeded on second attempt) are logged to Supabase but do not trigger a Slack alert.
Testing approach
All agents are built and tested in sandbox environments before connecting to production credentials. HubSpot sandbox account used for deal trigger testing. DocuSign developer sandbox account used for envelope creation and Connect webhook testing. Gmail test account used for follow-up email delivery verification. Slack test workspace used for interactive callback and notification testing. End-to-end flow tested with at least three representative deal types (retainer, project, SaaS) and at least two edge cases (missing required fields, declined DocuSign envelope) before production cutover.
Estimated total build time
Contract Assembly Agent: 10 hours. Signature Tracking and Follow-up Agent: 8 hours. Post-Signature CRM and Notification Agent: 6 hours. End-to-end integration testing and QA: 4 hours. Total: 28 hours across 4 build weeks, consistent with the confirmed build effort in the project snapshot.
Before build begins, the following must be confirmed with the process owner: (1) Google Drive template folder ID and complete list of template file IDs with their deal_type and region keys, (2) HubSpot deal property API names for all merge fields including any custom properties, (3) DocuSign account ID and confirmation that the Standard plan (Connect-enabled) is active, (4) Gmail shared mailbox address and OAuth consent granted for the contracts mailbox, (5) Slack channel names for review, error alerts, and the three completion notification channels, and (6) Supabase project URL and service role key for error logging. Do not begin workflow construction until items 1 through 3 are confirmed.
Support contact for this build: support@gofullspec.com. Reference the process template ID sales-contract-generation-and-e-sign and the deal name in all correspondence.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Contract Generation & E-sign.

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