Back to Affiliate Programme Management

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

Affiliate Programme Management

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

This document provides the complete technical reference for the Affiliate Programme Management automation build. It covers the current-state process map, all three agent specifications with IO contracts, the end-to-end data flow, and the recommended build stack. The FullSpec team uses this pack to configure, test, and deploy every component. No external developer input is required. The process owner's responsibilities are limited to confirming commission tier rules, providing tool credentials, and approving flagged conversions during parallel-run testing.

01Process snapshot

Step
Name
Description
1
Check Affiliate Platform for New Conversions
Marketing Manager logs into Tapfiliate and manually reviews all conversions recorded since the last check. Performed daily or every few days. Time cost: 20 min/cycle.
2
Verify Conversion Against Order System
Each conversion is cross-referenced against the order management system to confirm the sale is valid, non-duplicate, and not refunded. High error-risk step. Time cost: 30 min/cycle.
3
Update Commission Tracking Spreadsheet
Validated conversions are manually entered into a master Google Sheets log with affiliate name, sale value, commission rate, and calculated payout amount. Time cost: 25 min/cycle.
4
Log Deal and Attribution in CRM
The confirmed sale is added to HubSpot as a deal linked to the affiliate contact for attribution reporting. Time cost: 15 min/cycle.
5
Respond to Affiliate Queries via Email
Affiliates email to ask about stats or payment timing. Each reply is written individually with figures pulled manually from the spreadsheet. Time cost: 20 min/cycle.
6
Compile Monthly Payout Report
At month end the manager totals each affiliate's commissions from the spreadsheet and prepares a payout summary for finance. Highest error-risk step. Time cost: 40 min/cycle.
7
Raise Payout Bills in Xero
Finance Manager manually creates a bill in Xero for each affiliate based on the payout summary handed over by marketing. Time cost: 35 min/cycle.
8
Send Payment Confirmation Emails to Affiliates
Once payments are approved, the manager sends individual confirmation emails to each affiliate with payout amount and reference. Time cost: 20 min/cycle.
9
Onboard New Affiliate Partners
New affiliates are sent a welcome email, programme terms, unique tracking links, and creative assets manually each time someone is approved. Time cost: 25 min/cycle.
10
Post Performance Update to Internal Channel
A weekly summary of top-performing affiliates and total revenue is typed up and posted to the team Slack channel by hand. Time cost: 15 min/cycle.
Time cost summary: Total manual time per full cycle (daily + monthly tasks combined) is 245 minutes, equivalent to approximately 7 hours per week across the programme's recurring cadence. At ~120 conversions/month this represents $18,200/year in staff cost at the assumed $50/hour rate. Steps 2, 3, 6, 7, 8, 9, and 10 are fully replaced by automation. Step 4 (HubSpot logging) is fully automated. Step 5 (ad-hoc affiliate queries) and step 1 (platform check) are replaced by the webhook trigger. Step 1 becomes a system event. Only anomaly review (flagged conversions) and Xero bill approval remain with a human.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Conversion Validation Agent

Fires on every new confirmed conversion event received from Tapfiliate. The agent retrieves the conversion payload, cross-references it against order data to verify the sale is legitimate, checks for duplicate conversion IDs already present in the Google Sheets log, confirms the order has not been refunded, and applies the correct commission rate for the affiliate's tier. If any anomaly is detected (duplicate ID, order status mismatch, refund flag, or commission tier not resolvable) the agent sets a status flag of FLAGGED and halts downstream processing for that record, routing it for manual review. Clean records are written to the log with status PENDING_PAYOUT and passed downstream. Estimated build time: 14 hours. Complexity: Moderate.

Trigger
Tapfiliate conversion webhook (preferred) or scheduled API poll every 15 minutes if webhook is unavailable on the active Tapfiliate plan.
Tools
Tapfiliate (read conversion data), Google Sheets (duplicate check and record write)
Replaces steps
Step 2 (Verify Conversion Against Order System), Step 3 (Update Commission Tracking Spreadsheet)
Estimated build
14 hours, Moderate complexity
// Input: Tapfiliate conversion webhook payload
conversion_id       : string   // Tapfiliate unique conversion ID
affiliate_id        : string   // Tapfiliate affiliate identifier
affiliate_email     : string   // Affiliate email address
order_id            : string   // E-commerce order reference
order_value_usd     : float    // Gross order value in USD
conversion_date     : ISO8601  // UTC timestamp of conversion
commission_tier     : string   // Tier label from Tapfiliate (e.g. 'standard', 'vip')

// Output: validated commission record
conversion_id       : string   // Passed through unchanged
affiliate_id        : string   // Passed through unchanged
affiliate_email     : string   // Passed through unchanged
order_id            : string   // Passed through unchanged
order_value_usd     : float    // Confirmed gross value
commission_rate_pct : float    // Rate resolved from tier rules table
commission_amount   : float    // order_value_usd * commission_rate_pct
status              : enum     // 'PENDING_PAYOUT' | 'FLAGGED'
flag_reason         : string?  // Populated only when status = FLAGGED
logged_at           : ISO8601  // Timestamp of Sheets write
  • Tapfiliate plan must support either outbound webhooks or the Conversions API endpoint. Confirm the active plan tier before build. If webhooks are unavailable, configure a 15-minute polling interval and implement idempotency using conversion_id as the deduplication key in Google Sheets column A.
  • Commission tier rules must be documented in a named config sheet tab ('TierRules') within the same Google Sheets workbook before the agent goes live. The sheet must contain columns: tier_label, commission_rate_pct, effective_from. If a conversion arrives with an unrecognised tier_label, status must be set to FLAGGED with flag_reason 'tier_not_found'.
  • Duplicate detection: on each run, query column A of the 'CommissionLog' sheet for the incoming conversion_id before writing. If found, skip and log a dedup_skip event to the error log table.
  • Refund check: if the order_id maps to an order with status 'refunded' or 'cancelled' in the connected order data source, set status to FLAGGED with flag_reason 'order_refunded'. Confirm the order data source connection method with the process owner before build (direct API or Google Sheets export).
  • The Google Sheets workbook name and sheet tab names ('CommissionLog', 'TierRules') must be confirmed and fixed before build. Renaming tabs post-launch will break references.
  • Anomaly threshold: conversions where commission_amount exceeds $500 must always be set to FLAGGED for manual review regardless of other checks, unless this threshold is adjusted by the process owner in writing before go-live.
Payout and Communications Agent

This agent handles two distinct trigger paths. On a monthly schedule at payout cycle close it reads all PENDING_PAYOUT records from the Google Sheets log, groups them by affiliate_id, totals the commission_amount for each affiliate, raises a bill in Xero for each affiliate with the total owed, and marks those records as BILLED in the log. Once a Xero bill transitions to AUTHORISED status (finance approval), the agent sends a personalised payment confirmation email via Gmail. The second trigger path fires immediately when a new affiliate is approved in Tapfiliate: the agent retrieves the affiliate's profile data and dispatches the onboarding email sequence via Gmail. HubSpot deal records are created or updated on both paths to capture attribution. Estimated build time: 22 hours. Complexity: Complex.

Trigger
Monthly scheduled trigger at payout cycle close (configurable day-of-month, default last business day) AND immediate trigger on new affiliate approval event in Tapfiliate.
Tools
Xero (bill creation), Gmail (payment confirmation and onboarding emails), HubSpot (deal create/update)
Replaces steps
Step 4 (Log Deal in CRM), Step 6 (Compile Monthly Payout Report), Step 7 (Raise Payout Bills), Step 8 (Send Payment Confirmation Emails), Step 9 (Onboard New Affiliate Partners)
Estimated build
22 hours, Complex complexity
// Input (payout path): aggregated from Google Sheets CommissionLog
affiliate_id           : string   // Unique affiliate identifier
affiliate_email        : string   // Destination for confirmation email
affiliate_display_name : string   // Used in email personalisation
commission_records[]   : array    // All PENDING_PAYOUT rows for this affiliate
  .conversion_id       : string
  .order_value_usd     : float
  .commission_amount   : float
  .conversion_date     : ISO8601
total_commission_usd   : float    // Sum of commission_amount across records
payout_period_label    : string   // e.g. 'April 2025'

// Input (onboarding path): new affiliate approval event from Tapfiliate
affiliate_id           : string
affiliate_email        : string
affiliate_display_name : string
tracking_link          : string   // Unique referral URL from Tapfiliate
approved_at            : ISO8601

// Output (payout path)
xero_bill_id           : string   // Xero bill reference created
xero_bill_status       : enum     // 'DRAFT' | 'AWAITING_APPROVAL'
hubspot_deal_id        : string   // Created or updated deal ID
gmail_confirmation_sent: boolean  // True when confirmation email dispatched
sheets_status_updated  : enum     // 'BILLED' written back to CommissionLog

// Output (onboarding path)
gmail_welcome_sent     : boolean
hubspot_contact_id     : string   // Affiliate contact created/updated in HubSpot

// On approval (Xero bill AUTHORISED event)
xero_bill_id           : string   // Triggers Gmail confirmation send
payment_date           : ISO8601  // Expected transfer date from Xero
amount_paid_usd        : float
  • Xero bill creation requires the Xero Accounting API with Bills (Accounts Payable) write scope. Each affiliate must exist as a Contact in Xero. The agent must check for an existing Xero contact by affiliate_email before creating a new one to avoid duplicates. Contact creation must be confirmed with the Finance Manager before go-live.
  • Xero bills must be raised with status AWAITING_APPROVAL, never AUTHORISED. The automation must never progress a bill to payment. Finance approval remains a deliberate manual gate.
  • The Xero AUTHORISED webhook (or polling check every 10 minutes) triggers the Gmail payment confirmation send. Confirm which approach Xero supports on the active plan. If polling, implement idempotency so a single bill does not trigger multiple emails.
  • Gmail sending requires OAuth 2.0 with the gmail.send scope authenticated against the designated sender account. Confirm the sender address with the process owner. All outbound emails must use a named template stored in the automation platform, not inline HTML, so content can be updated without a rebuild.
  • HubSpot deal creation: confirm the HubSpot tier. The Deals API requires at minimum a Sales Hub Starter subscription or a CRM API key with deals:write scope. Deal pipeline and stage IDs must be retrieved from the HubSpot account before build and stored as config variables.
  • The onboarding email sequence must be defined as a multi-step template (welcome, programme terms, tracking link, creative assets) before build begins. FullSpec will not write copy; the process owner must supply or approve email content before the build stage for this agent starts.
  • Monthly schedule day must be confirmed by the process owner. Default is the last business day of each month. If the payout cycle uses a different cut-off, this must be specified in writing before build.
Reporting Agent

Fires every Monday morning on a fixed schedule. The agent reads all rows from the Google Sheets CommissionLog where conversion_date falls within the past seven days, calculates total conversions, total commission accrued, and ranks affiliates by commission_amount to identify top performers. It then composes a structured Slack message using a fixed template and posts it to the designated marketing Slack channel. No downstream actions are taken; this agent is read-only on all connected tools. Estimated build time: 6 hours. Complexity: Simple.

Trigger
Weekly schedule, every Monday at 08:00 local time (timezone confirmed with process owner before build).
Tools
Google Sheets (commission log read), Slack (message post)
Replaces steps
Step 10 (Post Performance Update to Internal Channel)
Estimated build
6 hours, Simple complexity
// Input: Google Sheets CommissionLog rows (past 7 days)
rows[]               : array
  .affiliate_id      : string
  .affiliate_email   : string
  .commission_amount : float
  .conversion_date   : ISO8601
  .status            : string   // Any status; all rows included in digest

// Output: computed digest values passed to Slack formatter
period_label         : string   // e.g. 'Week of 12 May 2025'
total_conversions    : integer  // Count of rows in date range
total_commission_usd : float    // Sum of commission_amount
top_affiliates[]     : array    // Top 3 by commission_amount
  .affiliate_email   : string
  .total_commission  : float
  .conversion_count  : integer
slack_message_posted : boolean
slack_channel_id     : string   // Resolved channel ID, not display name
  • Slack posting requires a Slack Bot Token with chat:write scope and the bot added to the target channel. Store the channel ID (not the display name) as a config variable. Confirm the target channel name and ID with the process owner before build.
  • If zero conversions are recorded in the past seven days, the agent must still post a digest message stating zero activity rather than skipping silently. This prevents the team from being uncertain whether the automation ran.
  • Google Sheets read must use a service account with Viewer permissions on the workbook. The same service account used by the Conversion Validation Agent is sufficient; confirm shared credential usage with the FullSpec build team.
  • Timezone for the Monday 08:00 trigger must be set explicitly in the scheduler config. Confirm with the process owner. Default assumption is the business's local timezone.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

End-to-end data flow: Affiliate Programme Management automation. All field names match Google Sheets column headers and API payload keys.
// ============================================================
// TRIGGER: Tapfiliate conversion event
// ============================================================
TAPFILIATE_WEBHOOK_EVENT
  -> conversion_id       : string
  -> affiliate_id        : string
  -> affiliate_email     : string
  -> order_id            : string
  -> order_value_usd     : float
  -> conversion_date     : ISO8601
  -> commission_tier     : string

// ============================================================
// AGENT 1 HANDOFF: Conversion Validation Agent receives payload
// ============================================================
CONVERSION_VALIDATION_AGENT
  [1] DEDUP CHECK: query Google Sheets CommissionLog column A
      IF conversion_id EXISTS -> emit dedup_skip_event, HALT
  [2] REFUND CHECK: query order system by order_id
      IF order_status IN ('refunded', 'cancelled') -> status = 'FLAGGED', flag_reason = 'order_refunded'
  [3] TIER LOOKUP: query TierRules sheet by commission_tier
      IF tier_label NOT FOUND -> status = 'FLAGGED', flag_reason = 'tier_not_found'
      IF tier_label FOUND -> commission_rate_pct = resolved_rate
  [4] AMOUNT CALC: commission_amount = order_value_usd * commission_rate_pct
      IF commission_amount > 500 -> status = 'FLAGGED', flag_reason = 'high_value_review'
  [5] WRITE to Google Sheets CommissionLog
      fields written:
        conversion_id, affiliate_id, affiliate_email, order_id,
        order_value_usd, commission_rate_pct, commission_amount,
        status ('PENDING_PAYOUT' | 'FLAGGED'), flag_reason, logged_at
  IF status = 'FLAGGED' -> HALT downstream, alert Marketing Manager
  IF status = 'PENDING_PAYOUT' -> continue

// ============================================================
// AGENT 2 HANDOFF (PATH A): Payout and Communications Agent
//   Trigger: monthly schedule at payout cycle close
// ============================================================
PAYOUT_AND_COMMUNICATIONS_AGENT (PAYOUT PATH)
  [1] READ Google Sheets CommissionLog
      filter: status = 'PENDING_PAYOUT'
      group by: affiliate_id
      aggregate: total_commission_usd = SUM(commission_amount)
      output fields per affiliate:
        affiliate_id, affiliate_email, affiliate_display_name,
        commission_records[], total_commission_usd, payout_period_label
  [2] XERO: check for existing Contact by affiliate_email
      IF NOT EXISTS -> create Xero Contact (name = affiliate_display_name, email = affiliate_email)
      CREATE Xero Bill
        contact_id    = xero_contact_id
        reference     = 'AFFILIATE-{affiliate_id}-{payout_period_label}'
        amount_due    = total_commission_usd
        currency      = USD
        status        = 'AWAITING_APPROVAL'
      -> xero_bill_id returned
  [3] HUBSPOT: create or update Deal
        deal_name     = 'Affiliate Commission - {affiliate_display_name} - {payout_period_label}'
        pipeline_id   = [config: confirmed pre-build]
        deal_stage_id = [config: confirmed pre-build]
        amount        = total_commission_usd
        affiliate_id  = custom property
      -> hubspot_deal_id returned
  [4] UPDATE Google Sheets CommissionLog
        status -> 'BILLED'
        xero_bill_id written to log row

// ============================================================
// AGENT 2 RESUME (PATH A): on Xero bill AUTHORISED
// ============================================================
XERO_BILL_AUTHORISED_EVENT
  -> xero_bill_id, amount_paid_usd, payment_date
PAYOUT_AND_COMMUNICATIONS_AGENT (POST-APPROVAL)
  [5] GMAIL: send payment confirmation email
        to             = affiliate_email
        template       = 'payment_confirmation_v1'
        variables:
          affiliate_display_name, amount_paid_usd, payment_date,
          payout_period_label, xero_bill_id
      -> gmail_confirmation_sent = true
  [6] UPDATE Google Sheets CommissionLog
        status -> 'PAID'

// ============================================================
// AGENT 2 HANDOFF (PATH B): new affiliate approved in Tapfiliate
// ============================================================
TAPFILIATE_AFFILIATE_APPROVED_EVENT
  -> affiliate_id, affiliate_email, affiliate_display_name,
     tracking_link, approved_at
PAYOUT_AND_COMMUNICATIONS_AGENT (ONBOARDING PATH)
  [1] HUBSPOT: create or update Contact
        email          = affiliate_email
        first_name     = affiliate_display_name (parsed)
        affiliate_id   = custom property
        lifecycle_stage = 'partner'
      -> hubspot_contact_id returned
  [2] GMAIL: send onboarding email sequence
        step_1: welcome email (immediate)
          template = 'affiliate_welcome_v1'
          variables: affiliate_display_name, tracking_link
        step_2: programme terms (delay: +1 day)
          template = 'affiliate_terms_v1'
        step_3: creative assets (delay: +2 days)
          template = 'affiliate_assets_v1'
      -> gmail_welcome_sent = true

// ============================================================
// AGENT 3 HANDOFF: Reporting Agent
//   Trigger: weekly Monday 08:00 schedule
// ============================================================
REPORTING_AGENT
  [1] READ Google Sheets CommissionLog
      filter: conversion_date >= NOW() - 7 days
      compute:
        total_conversions    = COUNT(rows)
        total_commission_usd = SUM(commission_amount)
        top_affiliates[]     = TOP 3 BY commission_amount (grouped by affiliate_id)
          .affiliate_email, .total_commission, .conversion_count
  [2] SLACK: post digest message
        channel_id = [config: confirmed pre-build]
        template   = 'weekly_digest_v1'
        variables:
          period_label, total_conversions, total_commission_usd,
          top_affiliates[0..2]
      IF total_conversions = 0 -> post zero-activity message (do not skip)
      -> slack_message_posted = true

// ============================================================
// ERROR PATH (all agents)
// ============================================================
ON_ERROR
  -> log error to Supabase error_log table:
       agent_name, step_label, error_code, error_message,
       input_payload_snapshot, occurred_at
  -> trigger Slack alert to #automation-errors channel
  -> retry policy: 3 attempts with exponential backoff (30s, 2min, 10min)
  -> after 3 failures: halt and await manual intervention
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation platform with native HTTP trigger support, a credential store, and multi-step branching. Deploy one workflow per agent (three workflows total): 'affiliate-conversion-validation', 'affiliate-payout-comms', and 'affiliate-reporting-digest'. All six tool credentials (Tapfiliate, Google Sheets, HubSpot, Xero, Gmail, Slack) are stored in a shared credential store and referenced by name across workflows. No credentials are hardcoded in workflow logic.
Webhook configuration
Tapfiliate conversion webhook: register the automation platform's inbound webhook URL in the Tapfiliate dashboard under Settings > Integrations > Webhooks. Event type: 'conversion_approved'. Payload format: JSON. Enable HMAC signature verification using the Tapfiliate webhook secret stored as an environment variable (TAPFILIATE_WEBHOOK_SECRET). If the active Tapfiliate plan does not support webhooks, configure a polling workflow with a 15-minute interval using the GET /conversions endpoint with a created_after query parameter persisted between runs. Xero bill status polling (or AUTHORISED webhook): register the automation platform URL in the Xero app's webhook subscriptions for the 'Invoice' event type filtered to AUTHORISED status. Tapfiliate affiliate approval trigger: poll GET /affiliates?status=approved with an approved_after cursor stored between runs, or use the affiliate webhook event if available.
Templating approach
All outbound Gmail emails use named templates stored as workflow-level text assets (not inline HTML in node config). Template IDs: 'payment_confirmation_v1', 'affiliate_welcome_v1', 'affiliate_terms_v1', 'affiliate_assets_v1'. Variable substitution uses double-brace syntax (e.g. {{affiliate_display_name}}). The Slack weekly digest uses a single named block-kit template ('weekly_digest_v1') with JSON-formatted section blocks. All templates must be reviewed and approved by the process owner before the agent build stage that depends on them begins. Template versioning: append _v2, _v3 on any content change; never overwrite a live template in place.
Error logging
All agent errors are written to a Supabase table named 'automation_error_log' with columns: id (uuid), agent_name (text), step_label (text), error_code (text), error_message (text), input_snapshot (jsonb), occurred_at (timestamptz), resolved (boolean, default false). On any error write, a Slack alert is posted to #automation-errors with a summary including agent name, step, error message, and a direct link to the Supabase row. Retry policy: 3 attempts with exponential backoff (30 seconds, 2 minutes, 10 minutes). After three failures the workflow halts and the Supabase row resolved field remains false until manually acknowledged.
Testing approach
All agents are built and validated in a sandbox environment first. Tapfiliate: use test conversion events from the Tapfiliate sandbox account. Google Sheets: use a duplicate workbook named 'CommissionLog_TEST' with identical schema. Xero: use the Xero demo company account for bill creation tests. HubSpot: use a sandbox portal or a dedicated test pipeline within the production portal, confirmed with the process owner. Gmail: send all test emails to an internal test alias (e.g. automation-test@[YourCompany.com]) before live affiliate addresses are used. Slack: post digests to a private test channel before switching to the live marketing channel. Parallel run of at least two full weekly cycles and one full monthly payout cycle is required before go-live.
Estimated total build time
Conversion Validation Agent: 14 hours. Payout and Communications Agent: 22 hours. Reporting Agent: 6 hours. End-to-end integration testing and QA: 6 hours. Total: 48 hours across approximately 5 delivery weeks.
Pre-build confirmation checklist: (1) Tapfiliate plan tier confirmed for webhook or API poll support. (2) Commission tier rules documented in the TierRules sheet with all tier labels, rates, and effective dates. (3) Google Sheets workbook shared with the build service account and tab names fixed ('CommissionLog', 'TierRules'). (4) HubSpot deal pipeline ID and stage IDs retrieved and stored as config. (5) Xero demo company access confirmed for sandbox testing. (6) Slack bot added to the target marketing channel and channel ID confirmed. (7) Gmail sender account OAuth consent completed and refresh token stored. (8) All email template copy approved by the process owner. (9) Monthly payout cycle cut-off day confirmed. (10) High-value commission anomaly threshold ($500 default) confirmed or adjusted in writing. Contact the FullSpec team at support@gofullspec.com if any item is blocked.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Affiliate Programme Management.

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