Automate a weekly pipeline report with HubSpot and Slack using Zapier

low complexityCost: $20-50/mo

Prerequisites

Prerequisites
  • Zapier account on the Professional plan or higher (required for multi-step Zaps, Code by Zapier, and Webhooks by Zapier)
  • HubSpot account connected to Zapier via OAuth
  • Slack workspace connected to Zapier

Overview

Zapier's built-in HubSpot integration doesn't have a "get all deals" action — it's designed around individual deal triggers. For a weekly aggregated report, you'll use Schedule by Zapier to trigger weekly, Webhooks by Zapier to call the HubSpot API directly, Code by Zapier to process the data, and Slack to deliver the report.

Why Webhooks instead of the built-in HubSpot actions?

Zapier's native HubSpot actions work on individual records (e.g., "New Deal" trigger). For a report that aggregates all pipeline deals, you need to call the HubSpot Search API directly using Webhooks by Zapier, which lets you make custom HTTP requests.

Step 1: Add a Schedule trigger

Create a new Zap. Choose Schedule by Zapier as the trigger:

  • Trigger event: Every Week
  • Day of the week: Monday
  • Time of day: 8:00am
  • Timezone: Select your team's timezone

Step 2: Fetch deals via Webhooks by Zapier

Add a Webhooks by Zapier action step:

  • Action event: Custom Request
  • Method: POST
  • URL: https://api.hubapi.com/crm/v3/objects/deals/search
  • Headers:
    • Authorization: Bearer YOUR_HUBSPOT_PRIVATE_APP_TOKEN
    • Content-Type: application/json
  • Data (raw JSON):
{
  "filterGroups": [
    {
      "filters": [
        {
          "propertyName": "pipeline",
          "operator": "EQ",
          "value": "default"
        }
      ]
    }
  ],
  "properties": [
    "dealname", "amount", "dealstage",
    "closedate", "hubspot_owner_id"
  ],
  "limit": 100
}
100-deal limit

The HubSpot Search API returns a max of 100 results per request. Zapier doesn't natively support looping through paginated API responses in a single Webhook step. If you have more than 100 active deals, you'll need to add additional Webhook steps with the after cursor, or use Code by Zapier to handle pagination.

Step 3: Process data with Code by Zapier

Add a Code by Zapier step (JavaScript) to parse the API response and calculate metrics:

  • Input Data: Map the response body from the Webhook step to a variable called rawData
const data = JSON.parse(inputData.rawData);
const deals = data.results || [];
 
let totalValue = 0;
const byStage = {};
 
for (const deal of deals) {
  const amount = parseFloat(deal.properties.amount || '0');
  totalValue += amount;
 
  const stage = deal.properties.dealstage || 'unknown';
  byStage[stage] = (byStage[stage] || 0) + 1;
}
 
const stageBreakdown = Object.entries(byStage)
  .map(([stage, count]) => `• ${stage}: ${count} deals`)
  .join('\n');
 
return {
  totalValue: totalValue.toLocaleString('en-US', {
    style: 'currency',
    currency: 'USD',
    maximumFractionDigits: 0
  }),
  dealCount: deals.length,
  stageBreakdown,
  reportDate: new Date().toLocaleDateString('en-US', {
    weekday: 'long',
    month: 'long',
    day: 'numeric',
    year: 'numeric'
  })
};
Code by Zapier limits

Code steps have a 30-second timeout (Pro plan and above; 10 seconds on Starter). The script runs in a sandboxed environment with no external HTTP requests — you can't call additional APIs from within Code by Zapier. All data must be passed in via Input Data.

Step 4: Send to Slack

Add a Slack action step:

  • Action event: Send Channel Message
  • Channel: #sales-reports
  • Message Text:
📊 *Weekly Pipeline Report*
 
*Total Pipeline:* {{totalValue}}
*Active Deals:* {{dealCount}}
 
*Deals by Stage:*
{{stageBreakdown}}
 
_Report generated {{reportDate}}_

If you need richer formatting with Block Kit, use a Webhooks by Zapier step instead to POST directly to the Slack API:

  • Method: POST
  • URL: https://slack.com/api/chat.postMessage
  • Headers: Authorization: Bearer xoxb-your-bot-token
  • Data: Block Kit JSON with sections, fields, and dividers
Block Kit via Slack's built-in action

Zapier's native "Send Channel Message" action supports basic mrkdwn formatting but not full Block Kit JSON. For formatted reports with columns and dividers, use the Webhooks approach to call chat.postMessage directly.

Step 5: Test and publish

  1. Click Test on each step to verify the data flows correctly
  2. Review the Slack message output — check that metrics and formatting look right
  3. Turn the Zap On

Cost and task usage

  • Professional plan: $29.99/mo (billed annually) with 750 tasks/month
  • This Zap uses ~4 tasks/month (one per Monday): 1 schedule trigger + 1 webhook + 1 code + 1 Slack = 4 steps, but Zapier counts each Zap run as tasks based on successful actions. Formatter and Filter steps no longer count toward task usage.
  • Code by Zapier rate limit: 225 calls per 10 seconds on Pro (increased from 75 in 2025)

Limitations

  • No native pagination: Zapier can't loop through HubSpot's paginated API results without Code or additional Webhook steps. For 100+ deals, this gets cumbersome.
  • No persistent state: You can't store last week's metrics for week-over-week comparison without an external store (Google Sheets, Zapier Tables).
  • Code step sandboxing: Code by Zapier can't make HTTP requests — all data must be passed in. Complex transformations may hit the 30-second timeout.
  • Stage names: The HubSpot API returns stage IDs (like closedwon), not labels. You'd need an additional Webhook step to fetch pipeline stages, or hardcode the mapping in your Code step.

Next steps

  • Add pipeline stage resolution — add a second Webhook step before the Code step to call GET /crm/v3/pipelines/deals and map stage IDs to labels
  • Store historical data — add a Google Sheets or Zapier Tables step to log metrics each week
  • Add filters — use Zapier's Filter step to only send the report if there are new deals (skip weeks with no changes)

Need help implementing this?

We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.