@thierryteisseire/woodpecker-skill 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/SKILL.md +78 -0
- package/package.json +31 -0
- package/scripts/setup_campaign.py +83 -0
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: woodpecker-campaign
|
|
3
|
+
description: Create and configure Woodpecker campaigns (V2) with correctly linked prospects (V1)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Woodpecker Campaign Setup Skill
|
|
7
|
+
|
|
8
|
+
This skill provides the definitive workflow for creating a Woodpecker campaign using the V2 API and correctly enrolling prospects using the V1 API, ensuring visual linkage and account signatures.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
1. **Get your API Key** from Woodpecker (Settings > Marketplace > API keys).
|
|
13
|
+
2. **Find your Email Account ID** (needed for campaign creation).
|
|
14
|
+
3. **Use the scripts** in this skill to automate the 2-step process.
|
|
15
|
+
|
|
16
|
+
## Key Findings & Gotchas
|
|
17
|
+
|
|
18
|
+
* **API Splitting**: Campaign creation should use **V2** (`/rest/v2/campaigns`). Prospect enrollment MUST use **V1** (`/rest/v1/add_prospects_campaign`).
|
|
19
|
+
* **The Linkage Secret**: To make prospects appear in the Woodpecker dashboard for a V2 campaign, you must nest the `campaign_id` inside a `campaign` object in the enrollment payload.
|
|
20
|
+
* **Signature Handling**: Setting `"signature": "SENDER"` in the V2 step body uses the account's configured professional signature automatically.
|
|
21
|
+
* **Status & Force**: Always set prospect status to `ACTIVE` and use `force: True` in the enrollment payload to override any prior global status.
|
|
22
|
+
|
|
23
|
+
## Workflow Patterns
|
|
24
|
+
|
|
25
|
+
### 1. Create Campaign (V2)
|
|
26
|
+
**Endpoint**: `POST https://api.woodpecker.co/rest/v2/campaigns`
|
|
27
|
+
**Header**: `X-API-KEY: YOUR_KEY`
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"name": "Campaign Name",
|
|
32
|
+
"email_account_ids": [123456],
|
|
33
|
+
"settings": {
|
|
34
|
+
"timezone": "Europe/Paris",
|
|
35
|
+
"daily_enroll": 50
|
|
36
|
+
},
|
|
37
|
+
"steps": {
|
|
38
|
+
"type": "START",
|
|
39
|
+
"followup": {
|
|
40
|
+
"type": "EMAIL",
|
|
41
|
+
"body": {
|
|
42
|
+
"versions": [{
|
|
43
|
+
"subject": "{{SNIPPET_2}}",
|
|
44
|
+
"message": "<div>Bonjour {{FIRST_NAME}},<br><br>{{SNIPPET_1}}</div>",
|
|
45
|
+
"signature": "SENDER"
|
|
46
|
+
}]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. Enroll Prospects (V1)
|
|
54
|
+
**Endpoint**: `POST https://api.woodpecker.co/rest/v1/add_prospects_campaign`
|
|
55
|
+
**Header**: `X-API-KEY: YOUR_KEY`
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"campaign": {
|
|
60
|
+
"campaign_id": 2418XXX
|
|
61
|
+
},
|
|
62
|
+
"force": true,
|
|
63
|
+
"prospects": [
|
|
64
|
+
{
|
|
65
|
+
"email": "lead@example.com",
|
|
66
|
+
"status": "ACTIVE",
|
|
67
|
+
"snippet1": "Personalized Message",
|
|
68
|
+
"snippet2": "Dynamic Subject"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Troubleshooting
|
|
75
|
+
|
|
76
|
+
* **200 OK but campaign is empty**: Check your payload nesting. Ensure `campaign_id` is inside `{"campaign": {"campaign_id": ...}}`.
|
|
77
|
+
* **Signature not showing**: Verify `"signature": "SENDER"` is in the step version body and that the email account has a signature set in Woodpecker.
|
|
78
|
+
* **Prospects added to list but not campaign**: This happens if the `campaign` object is missing from the V1 call.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: woodpecker-campaign
|
|
3
|
+
description: Create and configure Woodpecker campaigns (V2) with correctly linked prospects (V1)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Woodpecker Campaign Setup Skill
|
|
7
|
+
|
|
8
|
+
This skill provides the definitive workflow for creating a Woodpecker campaign using the V2 API and correctly enrolling prospects using the V1 API, ensuring visual linkage and account signatures.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
1. **Get your API Key** from Woodpecker (Settings > Marketplace > API keys).
|
|
13
|
+
2. **Find your Email Account ID** (needed for campaign creation).
|
|
14
|
+
3. **Use the scripts** in this skill to automate the 2-step process.
|
|
15
|
+
|
|
16
|
+
## Key Findings & Gotchas
|
|
17
|
+
|
|
18
|
+
* **API Splitting**: Campaign creation should use **V2** (`/rest/v2/campaigns`). Prospect enrollment MUST use **V1** (`/rest/v1/add_prospects_campaign`).
|
|
19
|
+
* **The Linkage Secret**: To make prospects appear in the Woodpecker dashboard for a V2 campaign, you must nest the `campaign_id` inside a `campaign` object in the enrollment payload.
|
|
20
|
+
* **Signature Handling**: Setting `"signature": "SENDER"` in the V2 step body uses the account's configured professional signature automatically.
|
|
21
|
+
* **Status & Force**: Always set prospect status to `ACTIVE` and use `force: True` in the enrollment payload to override any prior global status.
|
|
22
|
+
|
|
23
|
+
## Workflow Patterns
|
|
24
|
+
|
|
25
|
+
### 1. Create Campaign (V2)
|
|
26
|
+
**Endpoint**: `POST https://api.woodpecker.co/rest/v2/campaigns`
|
|
27
|
+
**Header**: `X-API-KEY: YOUR_KEY`
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"name": "Campaign Name",
|
|
32
|
+
"email_account_ids": [123456],
|
|
33
|
+
"settings": {
|
|
34
|
+
"timezone": "Europe/Paris",
|
|
35
|
+
"daily_enroll": 50
|
|
36
|
+
},
|
|
37
|
+
"steps": {
|
|
38
|
+
"type": "START",
|
|
39
|
+
"followup": {
|
|
40
|
+
"type": "EMAIL",
|
|
41
|
+
"body": {
|
|
42
|
+
"versions": [{
|
|
43
|
+
"subject": "{{SNIPPET_2}}",
|
|
44
|
+
"message": "<div>Bonjour {{FIRST_NAME}},<br><br>{{SNIPPET_1}}</div>",
|
|
45
|
+
"signature": "SENDER"
|
|
46
|
+
}]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. Enroll Prospects (V1)
|
|
54
|
+
**Endpoint**: `POST https://api.woodpecker.co/rest/v1/add_prospects_campaign`
|
|
55
|
+
**Header**: `X-API-KEY: YOUR_KEY`
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"campaign": {
|
|
60
|
+
"campaign_id": 2418XXX
|
|
61
|
+
},
|
|
62
|
+
"force": true,
|
|
63
|
+
"prospects": [
|
|
64
|
+
{
|
|
65
|
+
"email": "lead@example.com",
|
|
66
|
+
"status": "ACTIVE",
|
|
67
|
+
"snippet1": "Personalized Message",
|
|
68
|
+
"snippet2": "Dynamic Subject"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Troubleshooting
|
|
75
|
+
|
|
76
|
+
* **200 OK but campaign is empty**: Check your payload nesting. Ensure `campaign_id` is inside `{"campaign": {"campaign_id": ...}}`.
|
|
77
|
+
* **Signature not showing**: Verify `"signature": "SENDER"` is in the step version body and that the email account has a signature set in Woodpecker.
|
|
78
|
+
* **Prospects added to list but not campaign**: This happens if the `campaign` object is missing from the V1 call.
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thierryteisseire/woodpecker-skill",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Skill for setting up and managing Woodpecker campaigns correctly using API V2 and V1. Includes correctly linked prospect enrollment and signature automation.",
|
|
5
|
+
"main": "SKILL.md",
|
|
6
|
+
"bin": {
|
|
7
|
+
"woodpecker-setup": "./scripts/setup_campaign.py"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/thierryteisseire/woodpecker-skill.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"agent-skill",
|
|
15
|
+
"woodpecker",
|
|
16
|
+
"cold-email",
|
|
17
|
+
"sales-automation",
|
|
18
|
+
"email-campaign",
|
|
19
|
+
"prospecting"
|
|
20
|
+
],
|
|
21
|
+
"author": "Thierry Teisseire",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"files": [
|
|
24
|
+
"SKILL.md",
|
|
25
|
+
"README.md",
|
|
26
|
+
"scripts/"
|
|
27
|
+
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"requests": "^2.31.0"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
def create_woodpecker_campaign(api_key, account_id, name, subject_snippet="{{SNIPPET_2}}", body_html="<div>Bonjour {{FIRST_NAME}},<br><br>{{SNIPPET_1}}</div>"):
|
|
5
|
+
"""
|
|
6
|
+
Creates a Woodpecker V2 Campaign with optimized settings.
|
|
7
|
+
"""
|
|
8
|
+
url = "https://api.woodpecker.co/rest/v2/campaigns"
|
|
9
|
+
headers = {
|
|
10
|
+
"X-API-KEY": api_key,
|
|
11
|
+
"Content-Type": "application/json"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
payload = {
|
|
15
|
+
"name": name,
|
|
16
|
+
"email_account_ids": [int(account_id)],
|
|
17
|
+
"settings": {
|
|
18
|
+
"timezone": "Europe/Paris",
|
|
19
|
+
"prospect_timezone": True,
|
|
20
|
+
"daily_enroll": 50,
|
|
21
|
+
"gdpr_unsubscribe": True
|
|
22
|
+
},
|
|
23
|
+
"steps": {
|
|
24
|
+
"type": "START",
|
|
25
|
+
"followup": {
|
|
26
|
+
"type": "EMAIL",
|
|
27
|
+
"body": {
|
|
28
|
+
"versions": [
|
|
29
|
+
{
|
|
30
|
+
"subject": subject_snippet,
|
|
31
|
+
"message": body_html,
|
|
32
|
+
"signature": "SENDER", # Use account signature
|
|
33
|
+
"track_opens": True
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
"followup": None
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
resp = requests.post(url, headers=headers, json=payload)
|
|
43
|
+
if resp.status_code == 201:
|
|
44
|
+
campaign_id = resp.json().get("id")
|
|
45
|
+
print(f"SUCCESS: Campaign created with ID: {campaign_id}")
|
|
46
|
+
return campaign_id
|
|
47
|
+
else:
|
|
48
|
+
print(f"FAILED to create campaign: {resp.status_code}")
|
|
49
|
+
print(resp.text)
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
def enroll_prospects(api_key, campaign_id, prospects_list):
|
|
53
|
+
"""
|
|
54
|
+
Enrolls a list of prospects into a campaign using V1 with correct nesting.
|
|
55
|
+
"""
|
|
56
|
+
url = "https://api.woodpecker.co/rest/v1/add_prospects_campaign"
|
|
57
|
+
headers = {
|
|
58
|
+
"X-API-KEY": api_key,
|
|
59
|
+
"Content-Type": "application/json"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# Batch size of 50 is recommended for V1
|
|
63
|
+
batch_size = 50
|
|
64
|
+
for i in range(0, len(prospects_list), batch_size):
|
|
65
|
+
batch = prospects_list[i:i + batch_size]
|
|
66
|
+
|
|
67
|
+
payload = {
|
|
68
|
+
"campaign": {
|
|
69
|
+
"campaign_id": int(campaign_id)
|
|
70
|
+
},
|
|
71
|
+
"force": True, # Overrides status to ACTIVE
|
|
72
|
+
"prospects": batch
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
resp = requests.post(url, headers=headers, json=payload)
|
|
76
|
+
print(f"Batch {i//batch_size + 1}: Status {resp.status_code}")
|
|
77
|
+
if resp.status_code != 200:
|
|
78
|
+
print(f"Error in batch: {resp.text}")
|
|
79
|
+
|
|
80
|
+
# Usage Example:
|
|
81
|
+
# prospects = [{"email": "test@example.com", "first_name": "John", "snippet1": "Icebreaker"}]
|
|
82
|
+
# cid = create_woodpecker_campaign(YOUR_KEY, YOUR_ACC_ID, "New Campaign")
|
|
83
|
+
# if cid: enroll_prospects(YOUR_KEY, cid, prospects)
|