Send a Slack alert when a Pipedrive deal changes stage using a Claude Code skill

low complexityCost: Usage-based

Prerequisites

Compatible agents

This skill works with any agent that supports the Claude Code skills standard, including Claude Code, Claude Cowork, OpenAI Codex, and Google Antigravity.

Prerequisites
  • One of the agents listed above
  • Pipedrive account with API access (Growth plan or higher)
  • Slack bot with chat:write permission, added to the target channel
Environment Variables
# Pipedrive API token (Settings > Personal > Tools and Integrations > API)
PIPEDRIVE_API_TOKEN=your_value_here
# Your Pipedrive subdomain (e.g. 'yourcompany' from yourcompany.pipedrive.com)
PIPEDRIVE_COMPANY_DOMAIN=your_value_here
# Slack bot token starting with xoxb- (chat:write scope required)
SLACK_BOT_TOKEN=your_value_here
# Slack channel ID starting with C (right-click channel > View channel details)
SLACK_CHANNEL_ID=your_value_here

Why a Claude Code skill?

The other approaches in this guide are deterministic: they run the same logic every time, the same way. A Claude Code skill is different. You tell Claude what you want in plain language, and the skill gives it enough context to do it reliably.

That means you can say:

  • "Check for Pipedrive deals that changed stage in the last hour"
  • "What deals moved to Negotiation this week?"
  • "Post a summary of today's stage changes to #sales-leadership"

The skill contains workflow guidelines, API reference materials, and a message template that the agent reads on demand. When you invoke the skill, Claude reads these files, writes a script on the fly, runs it, and reports results. If you ask for something different next time — a longer lookback window, a filtered pipeline, a summary instead of individual posts — the agent adapts without you touching any code.

How it works

The skill directory has three parts:

  1. SKILL.md — workflow guidelines telling the agent what steps to follow, which env vars to use, and what pitfalls to avoid
  2. references/ — Pipedrive API patterns (REST endpoints, response formats, stage resolution) so the agent calls the right APIs with the right parameters
  3. templates/ — a Slack Block Kit template so messages are consistently formatted across runs

When invoked, the agent reads SKILL.md, consults the reference and template files as needed, writes a Python script, executes it, and reports what it posted. The reference files act as guardrails — the agent knows exactly which endpoints to hit and what the responses look like, so it doesn't have to guess.

What is a Claude Code skill?

A Claude Code skill is a reusable command you add to your project that Claude Code can run on demand. Skills live in a .claude/skills/ directory and are defined by a SKILL.md file that tells the agent what the skill does, when to run it, and what tools it's allowed to use.

In this skill, the agent doesn't run a pre-written script. Instead, SKILL.md provides workflow guidelines and points to reference files — API documentation, message templates — that the agent reads to generate and execute code itself. This is the key difference from a traditional script: the agent can adapt its approach based on what you ask for while still using the right APIs and message formats.

Once installed, you can invoke a skill as a slash command (e.g., /pd-deal-stage-alerts), or the agent will use it automatically when you give it a task where the skill is relevant. Skills are portable — anyone who clones your repo gets the same commands.

Step 1: Create the skill directory

mkdir -p .claude/skills/pd-deal-stage-alerts/{templates,references}

This creates the layout:

.claude/skills/pd-deal-stage-alerts/
├── SKILL.md                          # workflow guidelines + config
├── templates/
│   └── slack-alert.md                # Block Kit template for Slack messages
└── references/
    └── pipedrive-deals-api.md        # Pipedrive API patterns

Step 2: Write the SKILL.md

Create .claude/skills/pd-deal-stage-alerts/SKILL.md:

---
name: pd-deal-stage-alerts
description: Check for recent Pipedrive deal stage changes and post alerts to Slack
disable-model-invocation: true
allowed-tools: Bash, Read
---
 
## Goal
 
Check for Pipedrive deals modified in a given time window (default: last 1 hour) and post a formatted alert per deal to a Slack channel.
 
## Configuration
 
Read these environment variables:
 
- `PIPEDRIVE_API_TOKEN` — Pipedrive API token from Settings > Personal > Tools and Integrations > API (required)
- `PIPEDRIVE_COMPANY_DOMAIN` — your Pipedrive subdomain, e.g. "yourcompany" from yourcompany.pipedrive.com (required)
- `SLACK_BOT_TOKEN` — Slack bot token starting with xoxb- (required)
- `SLACK_CHANNEL_ID` — Slack channel ID starting with C (required)
 
Default lookback window: 1 hour. The user may request a different window.
 
## Workflow
 
1. Validate that all required env vars are set. If any are missing, print which ones and exit.
2. Fetch the list of pipeline stages from Pipedrive so you can resolve numeric `stage_id` values to human-readable names. See `references/pipedrive-deals-api.md` for the endpoint.
3. Query Pipedrive for deals modified in the lookback window using the Recents endpoint. See `references/pipedrive-deals-api.md` for the query and response shape.
4. For each deal, post a message to Slack using the Block Kit format in `templates/slack-alert.md`.
5. Print a summary of how many alerts were posted.
 
## Important notes
 
- Pipedrive updates deal timestamps on ANY field change, not just stage changes. Some results may not be actual stage transitions. Mention this in your summary.
- Stage IDs in Pipedrive are numeric (e.g., `stage_id: 3`). You must resolve them to human-readable names via the `/v1/stages` endpoint before posting alerts.
- The API token does not expire (unlike OAuth tokens). It remains valid until the user regenerates it in Pipedrive settings.
- `SLACK_CHANNEL_ID` must be the channel ID (starts with `C`), not the channel name.
- The Slack bot must be invited to the target channel or `chat.postMessage` will fail with `not_in_channel`.
- Use `urllib.request` for HTTP calls (no external dependencies required).

Understanding the SKILL.md

Unlike the script-based approach, this SKILL.md doesn't contain a Run: command pointing to a script. Instead, it provides:

SectionPurpose
GoalTells the agent what outcome to produce
ConfigurationWhich env vars to read and what defaults to use
WorkflowNumbered steps with pointers to reference files
Important notesNon-obvious context that prevents common mistakes

The allowed-tools: Bash, Read setting lets the agent both read reference files and execute code. The agent writes its own script based on the workflow steps and reference materials.

Step 3: Add reference files

templates/slack-alert.md

Create .claude/skills/pd-deal-stage-alerts/templates/slack-alert.md:

# Slack Alert Template
 
Use this Block Kit structure for each Pipedrive deal stage change alert.
 
## Block Kit JSON
 
```json
{
  "channel": "<SLACK_CHANNEL_ID>",
  "text": "Deal stage changed: <deal_title>",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": ":arrows_counterclockwise: *Deal Stage Changed*\n*<deal_title>* is now in *<stage_name>*\nValue: $<deal_value>"
      }
    },
    {
      "type": "context",
      "elements": [
        {
          "type": "mrkdwn",
          "text": "<<pipedrive_link>|View in Pipedrive>"
        }
      ]
    }
  ]
}
```
 
## Notes
 
- The top-level `text` field is required by the Slack API as a fallback for notifications and accessibility.
- The Pipedrive deal link format: `https://<PIPEDRIVE_COMPANY_DOMAIN>.pipedrive.com/deal/<DEAL_ID>`.
- Format the value with comma separators (e.g., $75,000 not $75000).
- `value` may be null if not set on the deal. Display "N/A" when null.
- To customize, you can add fields like organization name, owner, expected close date, or stage transition (previous → current).

references/pipedrive-deals-api.md

Create .claude/skills/pd-deal-stage-alerts/references/pipedrive-deals-api.md:

# Pipedrive Deals API Reference
 
## Fetch pipeline stages
 
Resolve numeric stage IDs to human-readable stage names.
 
**Request:**
 
```
GET https://api.pipedrive.com/v1/stages
```
 
**Headers / query params:**
 
```
api_token=<PIPEDRIVE_API_TOKEN>
```
 
**Response shape:**
 
```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "Qualified Lead",
      "pipeline_id": 1,
      "order_nr": 1
    },
    {
      "id": 2,
      "name": "Discovery",
      "pipeline_id": 1,
      "order_nr": 2
    },
    {
      "id": 3,
      "name": "Proposal Sent",
      "pipeline_id": 1,
      "order_nr": 3
    }
  ]
}
```
 
Build a dictionary mapping `id``name` so you can look up stage labels for each deal.
 
## Query recently modified deals
 
Use the Recents endpoint to find deals modified within a time window.
 
**Request:**
 
```
GET https://api.pipedrive.com/v1/recents?since_timestamp=<ISO_TIMESTAMP>&items=deal&limit=500
```
 
**Headers / query params:**
 
```
api_token=<PIPEDRIVE_API_TOKEN>
```
 
- `since_timestamp` is an ISO 8601 datetime string (e.g., `2026-03-06T13:00:00Z`). Calculate it by subtracting the lookback window from the current time.
- `items=deal` restricts results to deals only.
- `limit` controls page size (max 500).
 
**Response shape:**
 
```json
{
  "success": true,
  "data": [
    {
      "item": "deal",
      "id": 98765,
      "data": {
        "id": 98765,
        "title": "Meridian Health Platform Migration",
        "value": 75000,
        "currency": "USD",
        "status": "open",
        "stage_id": 3,
        "pipeline_id": 1,
        "owner_id": 12345,
        "org_id": 11111,
        "person_id": 54321,
        "expected_close_date": "2026-05-20",
        "update_time": "2026-03-06T14:30:00Z"
      }
    }
  ],
  "additional_data": {
    "pagination": {
      "start": 0,
      "limit": 500,
      "more_items_in_collection": false,
      "next_start": 500
    }
  }
}
```
 
## Additional useful fields
 
The deal object includes `org_id` and `person_id` for related records. To include organization or contact names, query those separately:
 
```
GET https://api.pipedrive.com/v1/organizations/<org_id>?api_token=<PIPEDRIVE_API_TOKEN>
GET https://api.pipedrive.com/v1/persons/<person_id>?api_token=<PIPEDRIVE_API_TOKEN>
```
 
## Notes
 
- Pipedrive uses numeric `stage_id` values, not human-readable names. Always resolve via the `/v1/stages` endpoint.
- `value` is a number (not a string). It may be null if the deal value hasn't been set.
- The `more_items_in_collection` field indicates whether additional pages exist. If `true`, use `start=<next_start>` to fetch the next page.
- API tokens do not expire. They remain valid until regenerated in Pipedrive settings.
- Rate limits: token-based daily budget (30,000 base tokens x plan multiplier x seats). A single deal fetch costs 1 token. A 429 response means the daily budget is exhausted.

Step 4: Test the skill

Invoke the skill conversationally:

/pd-deal-stage-alerts

Claude will read the SKILL.md, check the reference files, write a script, run it, and report the results. A typical run looks like:

Checking for deals modified in the last 1 hour(s)...
  Fetched 8 pipeline stages
  Found 3 modified deal(s)
  Posted: Meridian Health Platform Migration → Proposal Sent
  Posted: Contoso Platform Expansion → Negotiation
  Posted: Acme Corp Annual Renewal → Closed Won
Done. Posted 3 alert(s) to Slack.
Note: Pipedrive updates timestamps on any field change, so some alerts
may be for non-stage modifications.

What the Slack alert looks like

What you'll get
#sales-alerts
Pipedrive Botapp9:41 AM

🔄 Deal Stage Changed

Meridian Health Platform Migration is now in Proposal Sent

Value: $75,000

View in Pipedrive

Because the agent generates code on the fly, you can also make ad hoc requests:

  • "Check for stage changes in the last 4 hours" — the agent adjusts the lookback window
  • "What deals moved to Closed Won this week?" — the agent adds a stage filter and widens the window
  • "Post a summary of today's stage changes to #sales-leadership" — the agent adapts the output format and channel
Test with a real deal

Move a deal to a different stage in Pipedrive, wait a few seconds, then run the skill. If no deals were modified in the last hour, you'll see "No deals modified" — which is correct, not an error.

Step 5: Schedule it (optional)

Option A: Cron + Claude CLI

# Run every hour on the hour
0 * * * * cd /path/to/your/project && claude -p "Run /pd-deal-stage-alerts" --allowedTools 'Bash(*)' 'Read(*)'

Option B: GitHub Actions + Claude

name: Pipedrive Deal Stage Alerts
on:
  schedule:
    - cron: '0 * * * *'  # Every hour
  workflow_dispatch: {}   # Manual trigger for testing
jobs:
  alert:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: anthropics/claude-code-action@v1
        with:
          prompt: "Run /pd-deal-stage-alerts"
          allowed_tools: "Bash(*),Read(*)"
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          PIPEDRIVE_API_TOKEN: ${{ secrets.PIPEDRIVE_API_TOKEN }}
          PIPEDRIVE_COMPANY_DOMAIN: ${{ secrets.PIPEDRIVE_COMPANY_DOMAIN }}
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
          SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }}
GitHub Actions schedules run in UTC

GitHub Actions cron schedules use UTC. If your sales team is in US Eastern, 0 * * * * (every hour UTC) means the first run after business hours starts at 9 AM ET = 1 PM UTC. Adjust accordingly if you want alerts only during working hours. Also, GitHub may delay scheduled runs by up to 15 minutes during periods of high load.

Option C: Cowork Scheduled Tasks

Claude Desktop's Cowork supports built-in scheduled tasks. Open a Cowork session, type /schedule, and configure the cadence — hourly, daily, weekly, or weekdays only. Each scheduled run has full access to your connected tools, plugins, and MCP servers.

Scheduled tasks only run while your computer is awake and Claude Desktop is open. If a run is missed, Cowork executes it automatically when the app reopens. For always-on scheduling, use GitHub Actions (Option B) instead. Available on all paid plans (Pro, Max, Team, Enterprise).

Troubleshooting

When to use this approach

  • You want conversational flexibility — ad hoc queries like "what moved to Negotiation this week?" alongside scheduled checks
  • You want on-demand alerts during pipeline reviews or standups, not just automated notifications
  • You're already using Claude Code and want skills that integrate with your workflow
  • You want to run tasks in the background via Claude Cowork while focusing on other work
  • You prefer guided references over rigid scripts — the agent adapts while staying reliable

When to switch approaches

  • You need real-time alerts (under 1 minute latency) → use Pipedrive Workflow Automation or n8n
  • You want a no-code setup with zero external tools → use Pipedrive Workflow Automation (it's free on Growth+)
  • You need rich Slack formatting with stage transitions (previous → current) → use n8n (webhooks include previous_data)
This skill detects modified deals, not stage changes specifically

Pipedrive's Recents endpoint returns deals modified for any reason — not just stage transitions. Some alerts may fire for deals where the value, owner, or another field was updated without a stage change. The SKILL.md documents this so the agent can flag it in its output. For true stage-change detection with previous/current stage context, use the n8n approach with Pipedrive webhooks, which include a previous_data object showing exactly what changed.

Common questions

Why not just use a script?

A script runs the same way every time. The Claude Code skill adapts to what you ask — different lookback windows, filtered stages, summary format instead of individual posts, a different channel. The reference files ensure it calls the right APIs even when improvising, so you get flexibility without sacrificing reliability.

Does this use Claude API credits?

Yes. The agent reads skill files and generates code each time. Typical cost is $0.01-0.05 per invocation depending on how many deals are returned. The Pipedrive and Slack APIs themselves are included in their respective plans.

How do I manage the Pipedrive API token?

Pipedrive API tokens do not expire — they remain valid until regenerated. Store the token in an environment variable and never commit it to source control. If you suspect the token is compromised, regenerate it in Settings > Personal > Tools and Integrations > API. The old token is immediately invalidated.

Can I run this skill on a schedule without a server?

Yes. GitHub Actions (Option B in Step 5) runs Claude on a cron schedule using GitHub's infrastructure. The free tier includes 2,000 minutes/month.

Cost

  • Claude API — $0.01-0.05 per invocation (the agent reads files and generates code)
  • Pipedrive API — included in Growth plan and above, token-based daily budget (30,000+ tokens/day)
  • Slack API — included in all plans, no per-call cost
  • GitHub Actions (if scheduled) — free tier includes 2,000 minutes/month

Looking to scale your AI operations?

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