n8n-nodes-adspirer 0.2.0 → 0.3.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 +164 -194
- package/dist/credentials/AdspireApi.credentials.js +9 -6
- package/dist/credentials/AdspireApi.credentials.js.map +1 -1
- package/dist/nodes/Adspirer/Adspirer.node.d.ts +9 -1
- package/dist/nodes/Adspirer/Adspirer.node.js +205 -69
- package/dist/nodes/Adspirer/Adspirer.node.js.map +1 -1
- package/dist/nodes/Adspirer/generated/tools.d.ts +22 -0
- package/dist/nodes/Adspirer/generated/tools.js +5608 -0
- package/dist/nodes/Adspirer/generated/tools.js.map +1 -0
- package/dist/nodes/Adspirer/shared/build-properties.d.ts +13 -0
- package/dist/nodes/Adspirer/shared/build-properties.js +192 -0
- package/dist/nodes/Adspirer/shared/build-properties.js.map +1 -0
- package/dist/nodes/Adspirer/shared/descriptions.d.ts +1 -3
- package/dist/nodes/Adspirer/shared/descriptions.js +3 -37
- package/dist/nodes/Adspirer/shared/descriptions.js.map +1 -1
- package/dist/nodes/Adspirer/shared/toolMapping.d.ts +12 -6
- package/dist/nodes/Adspirer/shared/toolMapping.js +48 -107
- package/dist/nodes/Adspirer/shared/toolMapping.js.map +1 -1
- package/package.json +8 -4
- package/dist/credentials/AdspireOAuth2Api.credentials.d.ts +0 -10
- package/dist/credentials/AdspireOAuth2Api.credentials.js +0 -53
- package/dist/credentials/AdspireOAuth2Api.credentials.js.map +0 -1
- package/dist/nodes/Adspirer/resources/googleAds.d.ts +0 -3
- package/dist/nodes/Adspirer/resources/googleAds.js +0 -279
- package/dist/nodes/Adspirer/resources/googleAds.js.map +0 -1
- package/dist/nodes/Adspirer/resources/metaAds.d.ts +0 -3
- package/dist/nodes/Adspirer/resources/metaAds.js +0 -120
- package/dist/nodes/Adspirer/resources/metaAds.js.map +0 -1
package/README.md
CHANGED
|
@@ -3,83 +3,35 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/n8n-nodes-adspirer)
|
|
4
4
|
[](LICENSE.md)
|
|
5
5
|
|
|
6
|
-
[n8n](https://n8n.io/) community node for [Adspirer](https://adspirer.ai) —
|
|
6
|
+
[n8n](https://n8n.io/) community node for [Adspirer](https://adspirer.ai) — orchestrate ad campaigns across **Google Ads, Meta, LinkedIn, and TikTok** from any n8n workflow.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Pick a platform, pick an operation, plug in your API key — n8n does the rest.
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
11
|
<img src="icons/adspirer.svg" alt="Adspirer" width="80" />
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Features
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
**
|
|
21
|
-
**
|
|
22
|
-
**Plugin Repo:** [`amekala/ads-mcp`](https://github.com/amekala/ads-mcp)
|
|
23
|
-
|
|
24
|
-
## Operations
|
|
25
|
-
|
|
26
|
-
### Google Ads (7 operations)
|
|
27
|
-
|
|
28
|
-
| Operation | Description |
|
|
29
|
-
|-----------|-------------|
|
|
30
|
-
| **Budget Optimization** | Get budget allocation and optimization recommendations |
|
|
31
|
-
| **Campaign Performance** | Get performance metrics for all campaigns over a date range |
|
|
32
|
-
| **Create PMax Campaign** | Create a new Performance Max campaign with assets |
|
|
33
|
-
| **Create Search Campaign** | Create a new Google Search campaign with keywords and ads |
|
|
34
|
-
| **Keyword Research** | Research keywords with real CPC, search volume, and competition data |
|
|
35
|
-
| **Search Terms Analysis** | Analyze search term performance and find negative keyword opportunities |
|
|
36
|
-
| **Wasted Spend Analysis** | Identify wasted ad spend and get optimization recommendations |
|
|
37
|
-
|
|
38
|
-
### Meta Ads (3 operations)
|
|
39
|
-
|
|
40
|
-
| Operation | Description |
|
|
41
|
-
|-----------|-------------|
|
|
42
|
-
| **Ad Performance** | Analyze individual ad and creative performance with fatigue detection |
|
|
43
|
-
| **Audience Insights** | Get audience demographics, placement analysis, and targeting insights |
|
|
44
|
-
| **Campaign Performance** | Get performance metrics for Meta ad campaigns |
|
|
45
|
-
|
|
46
|
-
### AI Agent Compatible
|
|
47
|
-
|
|
48
|
-
All operations are available as AI agent tools (`usableAsTool: true`). Add the Adspirer node as a tool to any n8n AI Agent and it can call any operation based on natural language instructions.
|
|
49
|
-
|
|
50
|
-
## Authentication
|
|
51
|
-
|
|
52
|
-
### OAuth2 (Recommended)
|
|
53
|
-
|
|
54
|
-
1. Add the Adspirer node to your workflow
|
|
55
|
-
2. Select **OAuth2 (Recommended)** authentication
|
|
56
|
-
3. Click **Connect** — a browser window opens for OAuth authorization
|
|
57
|
-
4. Sign in with your [Adspirer account](https://adspirer.ai) and authorize access
|
|
58
|
-
5. Your credentials are saved — all future workflows use the same connection
|
|
59
|
-
|
|
60
|
-
No API keys to manage. OAuth tokens refresh automatically.
|
|
61
|
-
|
|
62
|
-
### API Key
|
|
63
|
-
|
|
64
|
-
1. Sign up at [adspirer.ai](https://adspirer.ai) (free tier: 15 tool calls/month)
|
|
65
|
-
2. Get your API key from your account settings
|
|
66
|
-
3. Add the Adspirer node to your workflow
|
|
67
|
-
4. Select **API Key** authentication
|
|
68
|
-
5. Paste your API key
|
|
16
|
+
- **~120 operations** across 5 resource groups: Google Ads, Meta Ads, LinkedIn Ads, TikTok Ads, and Utility diagnostics
|
|
17
|
+
- **REST-native** — calls `https://api.adspirer.ai` via standard HTTP + Bearer auth. No SSE, no JSON-RPC
|
|
18
|
+
- **Quota-aware** — every response includes your remaining monthly allowance in `$item.json._adspirer_quota`
|
|
19
|
+
- **Idempotency built-in** — write operations automatically send an `Idempotency-Key` so retries don't double-charge you or duplicate campaigns
|
|
20
|
+
- **AI Agent compatible** — set `usableAsTool: true`, surfaces directly in n8n's AI Agent tool picker
|
|
21
|
+
- **Upgrade-aware errors** — a 402 quota response surfaces the Adspirer upgrade URL directly in the node's error output
|
|
69
22
|
|
|
70
23
|
## Installation
|
|
71
24
|
|
|
72
|
-
### n8n
|
|
25
|
+
### n8n (Cloud or self-hosted)
|
|
73
26
|
|
|
74
27
|
1. Open your n8n instance
|
|
75
|
-
2.
|
|
76
|
-
3.
|
|
77
|
-
4.
|
|
78
|
-
5. Click **Install**
|
|
28
|
+
2. **Settings → Community Nodes → Install a community node**
|
|
29
|
+
3. Enter `n8n-nodes-adspirer`
|
|
30
|
+
4. Click **Install** — the node appears in the nodes panel under "Adspirer"
|
|
79
31
|
|
|
80
|
-
The
|
|
32
|
+
The node is searchable by: `Adspirer`, `ads`, `Google Ads`, `Meta Ads`, `LinkedIn Ads`, `TikTok Ads`, `campaign`, `keyword research`, `ppc`.
|
|
81
33
|
|
|
82
|
-
### Self-
|
|
34
|
+
### Self-hosted via npm
|
|
83
35
|
|
|
84
36
|
```bash
|
|
85
37
|
cd ~/.n8n
|
|
@@ -87,140 +39,168 @@ npm install n8n-nodes-adspirer
|
|
|
87
39
|
# Restart n8n
|
|
88
40
|
```
|
|
89
41
|
|
|
90
|
-
|
|
42
|
+
## Authentication
|
|
43
|
+
|
|
44
|
+
The node uses an API key. There is currently no OAuth2 option — the hosted REST API doesn't expose public OAuth endpoints yet.
|
|
45
|
+
|
|
46
|
+
1. Sign up at [adspirer.ai](https://adspirer.ai) — free tier includes 15 tool calls/month, no credit card
|
|
47
|
+
2. Generate a key at [adspirer.ai/keys](https://adspirer.ai/keys) — keys are prefixed `sk_live_`, treat them as secrets
|
|
48
|
+
3. In n8n: **Credentials → New → Adspirer API**, paste the key, save
|
|
49
|
+
4. The credential test runs a free diagnostic call (`list_connected_accounts`) — expect a green ✓
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
After creating the credential:
|
|
54
|
+
|
|
55
|
+
1. Drop the **Adspirer** node onto any workflow
|
|
56
|
+
2. Pick a **Platform** — Google Ads, Meta Ads, LinkedIn Ads, TikTok Ads, or Utility
|
|
57
|
+
3. Pick an **Operation** from the dropdown (operations are filtered by platform)
|
|
58
|
+
4. Fill required fields. Optional fields can be left blank.
|
|
59
|
+
5. Execute
|
|
60
|
+
|
|
61
|
+
Each successful execution returns:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"success": true,
|
|
66
|
+
"platform": "googleAds",
|
|
67
|
+
"operation": "listCampaigns",
|
|
68
|
+
"tool": "list_campaigns",
|
|
69
|
+
"text": "# 📋 Your Google Ads Campaigns\n\n**Total Campaigns:** 10\n...",
|
|
70
|
+
"structured": null,
|
|
71
|
+
"_adspirer_quota": {
|
|
72
|
+
"used": 8,
|
|
73
|
+
"limit": 150,
|
|
74
|
+
"tier": "plus",
|
|
75
|
+
"period_end": "2026-05-17"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
- **`text`** — human-readable markdown summary of the result
|
|
81
|
+
- **`structured`** — structured payload when the operation returns one (null otherwise)
|
|
82
|
+
- **`_adspirer_quota`** — branch on this in subsequent nodes to avoid hitting your monthly limit
|
|
83
|
+
|
|
84
|
+
### Error handling
|
|
91
85
|
|
|
92
|
-
|
|
86
|
+
| HTTP code | Meaning | Node behavior |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| `200` | Success | returns data |
|
|
89
|
+
| `400` | Tool-level error (e.g. missing account) | throws with the error message |
|
|
90
|
+
| `401` | Invalid/missing API key | throws with key-regeneration hint |
|
|
91
|
+
| `402` | Monthly quota exhausted | throws with `upgrade_url` appended to the message |
|
|
92
|
+
| `429` | Upstream ad platform rate-limited us | throws — enable **Retry on Fail** in node settings (30–60s backoff recommended) |
|
|
93
|
+
| `5xx` | Server error | throws — enable **Retry on Fail** in node settings |
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
Use n8n's per-node **Retry on Fail** setting instead of a custom backoff loop — it's the idiomatic pattern and compatible with n8n Cloud's verification requirements.
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
## Example workflows
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
### 1. Daily wasted-spend check across all platforms
|
|
99
100
|
|
|
100
101
|
```
|
|
101
|
-
Schedule Trigger (daily
|
|
102
|
-
→ Adspirer:
|
|
103
|
-
→ Adspirer:
|
|
104
|
-
→
|
|
105
|
-
→
|
|
102
|
+
Schedule Trigger (daily 8am)
|
|
103
|
+
→ Adspirer: Google Ads → Analyze Wasted Spend (lookback: 7)
|
|
104
|
+
→ Adspirer: Meta Ads → Analyze Meta Wasted Spend (lookback: 7)
|
|
105
|
+
→ Adspirer: LinkedIn Ads → Analyze LinkedIn Wasted Spend (lookback: 7)
|
|
106
|
+
→ Code: merge + threshold check
|
|
107
|
+
→ IF > $50 wasted → Slack #marketing
|
|
106
108
|
```
|
|
107
109
|
|
|
108
|
-
### 2.
|
|
109
|
-
|
|
110
|
-
Catch budget waste early with weekly automated analysis.
|
|
110
|
+
### 2. New Shopify product → Google PMax campaign
|
|
111
111
|
|
|
112
112
|
```
|
|
113
|
-
|
|
114
|
-
→ Adspirer:
|
|
115
|
-
|
|
116
|
-
→
|
|
117
|
-
|
|
118
|
-
→ No: skip
|
|
113
|
+
Shopify Trigger (new product)
|
|
114
|
+
→ Adspirer: Google Ads → Create PMax Campaign
|
|
115
|
+
(name: {{ $json.title }}, budget: 30, final_url: {{ $json.url }})
|
|
116
|
+
→ Slack: post campaign link
|
|
117
|
+
→ Google Sheets: log in tracker
|
|
119
118
|
```
|
|
120
119
|
|
|
121
|
-
### 3.
|
|
122
|
-
|
|
123
|
-
Automatically create ad campaigns when new products are added.
|
|
120
|
+
### 3. Weekly cross-platform report to Google Sheets
|
|
124
121
|
|
|
125
122
|
```
|
|
126
|
-
|
|
127
|
-
→ Adspirer:
|
|
128
|
-
→
|
|
129
|
-
→
|
|
123
|
+
Schedule Trigger (Monday 9am)
|
|
124
|
+
→ Adspirer: Google Ads → Get Campaign Performance (lookback: 7)
|
|
125
|
+
→ Adspirer: Meta Ads → Analyze Meta Ad Performance (lookback: 7)
|
|
126
|
+
→ Code: normalize metrics
|
|
127
|
+
→ Google Sheets: append row
|
|
128
|
+
→ Gmail: send to client
|
|
130
129
|
```
|
|
131
130
|
|
|
132
|
-
### 4.
|
|
131
|
+
### 4. Quota-aware agent loop
|
|
133
132
|
|
|
134
|
-
|
|
133
|
+
```
|
|
134
|
+
Manual Trigger
|
|
135
|
+
→ Adspirer: Utility → Get Usage Status
|
|
136
|
+
→ IF _adspirer_quota.used < _adspirer_quota.limit * 0.8
|
|
137
|
+
Yes → AI Agent with Adspirer tool
|
|
138
|
+
No → Slack: "Quota near limit, skipping optimization run"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 5. HubSpot deal won → LinkedIn retargeting
|
|
135
142
|
|
|
136
143
|
```
|
|
137
|
-
HubSpot Trigger (deal stage
|
|
138
|
-
→ Adspirer:
|
|
139
|
-
→ Adspirer:
|
|
140
|
-
→
|
|
144
|
+
HubSpot Trigger (deal stage = "Closed Won")
|
|
145
|
+
→ Adspirer: LinkedIn Ads → Add LinkedIn Creative (custom ad for customer)
|
|
146
|
+
→ Adspirer: LinkedIn Ads → Create LinkedIn Sponsored Content
|
|
147
|
+
→ Slack: notify account manager
|
|
141
148
|
```
|
|
142
149
|
|
|
143
|
-
|
|
150
|
+
## AI Agent usage
|
|
144
151
|
|
|
145
|
-
|
|
152
|
+
Every Adspirer operation is available as an AI Agent tool (`usableAsTool: true`). Add the Adspirer node to an **AI Agent** node's tool slot, configure the agent's model (Claude / GPT-4 / etc.), and the agent can pick operations from natural-language instructions:
|
|
146
153
|
|
|
147
154
|
```
|
|
148
155
|
Chat Trigger (Slack)
|
|
149
|
-
→ AI Agent (Claude
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
→ Slack: post response
|
|
156
|
+
→ AI Agent (Claude)
|
|
157
|
+
tools: Adspirer, Google Sheets
|
|
158
|
+
→ Slack reply
|
|
153
159
|
```
|
|
154
160
|
|
|
155
|
-
**Example
|
|
156
|
-
- "
|
|
157
|
-
- "
|
|
158
|
-
- "
|
|
161
|
+
**Example prompts that work:**
|
|
162
|
+
- *"What are my top 3 Google Ads campaigns by ROAS this week?"*
|
|
163
|
+
- *"Find wasted spend across all my Meta ad sets over the last 30 days"*
|
|
164
|
+
- *"List all my connected ad accounts"*
|
|
159
165
|
|
|
160
|
-
|
|
166
|
+
For **full agentic access to all ~180 Adspirer tools** (including ones that stream their response and aren't exposed by this REST-based node), use the [`n8n-nodes-mcp`](https://www.npmjs.com/package/n8n-nodes-mcp) community node pointed at `https://mcp.adspirer.com/mcp` with your `sk_live_` key as the Bearer token.
|
|
161
167
|
|
|
162
|
-
|
|
168
|
+
## Operations summary
|
|
163
169
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
```
|
|
170
|
+
| Platform | Exposed | Notes |
|
|
171
|
+
|---|---|---|
|
|
172
|
+
| Google Ads | ~28 | Analytics, search term / keyword research, campaign ops, demand-gen |
|
|
173
|
+
| Meta Ads | ~27 | Ad/audience analytics, campaign creation (single + carousel + DCO) |
|
|
174
|
+
| LinkedIn Ads | ~32 | Creatives, campaign groups, conversions, lead forms, wasted spend |
|
|
175
|
+
| TikTok Ads | ~20 | Campaign creation, geo/creative fatigue analytics |
|
|
176
|
+
| Utility | ~12 | Diagnostics: `list_connected_accounts`, `get_usage_status`, monitors, audits |
|
|
172
177
|
|
|
173
|
-
|
|
178
|
+
**~60 additional tools** (complex creatives, asset bundles, detailed audience targeting) are exposed via the [REST API](https://api.adspirer.ai/docs) directly — those use array/object argument shapes that don't flatten into n8n's field UI. Invoke them with n8n's built-in **HTTP Request** node pointed at `POST https://api.adspirer.ai/api/v1/tools/{tool_name}/execute` using the same Adspirer API credential.
|
|
174
179
|
|
|
175
|
-
|
|
176
|
-
|----------|-------|----------|
|
|
177
|
-
| **Triggers** | Schedule, Webhook, Cron | Start monitoring/reporting workflows |
|
|
178
|
-
| **CRM** | HubSpot, Salesforce, Pipedrive | Deal events → campaign creation |
|
|
179
|
-
| **E-commerce** | Shopify, WooCommerce, Stripe | Product/order events → ad campaigns |
|
|
180
|
-
| **Messaging** | Slack, Gmail, Teams, Discord, Twilio | Alerts, reports, notifications |
|
|
181
|
-
| **Spreadsheets** | Google Sheets, Airtable, Notion | Dashboards, logging, tracking |
|
|
182
|
-
| **AI** | AI Agent, OpenAI, Anthropic | Natural language ad management |
|
|
183
|
-
| **Logic** | IF, Switch, Code, Merge | Threshold checks, data formatting |
|
|
184
|
-
| **Forms** | Typeform, Google Forms | Client briefs → campaign setup |
|
|
180
|
+
Live OpenAPI spec: https://api.adspirer.ai/openapi.json — regenerated automatically whenever the surface changes upstream.
|
|
185
181
|
|
|
186
182
|
## Pricing
|
|
187
183
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
| Plan | Tool Calls/Month | Price |
|
|
191
|
-
|------|-----------------|-------|
|
|
184
|
+
| Plan | Tool calls / month | Price |
|
|
185
|
+
|---|---|---|
|
|
192
186
|
| Free | 15 | $0 |
|
|
193
187
|
| Plus | 150 | $49/mo |
|
|
194
188
|
| Pro | 600 | $99/mo |
|
|
195
189
|
| Max | 3,000 | $199/mo |
|
|
196
190
|
|
|
197
|
-
Sign up at [adspirer.ai](https://adspirer.ai).
|
|
198
|
-
|
|
199
|
-
## Alternative: n8n Built-in MCP Nodes
|
|
191
|
+
Sign up at [adspirer.ai](https://adspirer.ai).
|
|
200
192
|
|
|
201
|
-
|
|
193
|
+
## Related
|
|
202
194
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
4. Authenticate via OAuth 2.1 or Bearer token
|
|
207
|
-
|
|
208
|
-
This gives you access to all 100+ Adspirer tools via the AI agent. The community node (this package) provides a more structured experience with typed operations and field validation for deterministic workflows.
|
|
209
|
-
|
|
210
|
-
## Related Projects
|
|
211
|
-
|
|
212
|
-
| Project | Description | Link |
|
|
213
|
-
|---------|-------------|------|
|
|
214
|
-
| **ads-mcp** | Adspirer MCP server registration + multi-IDE plugins (Claude Code, Cursor, Codex, OpenClaw) | [github.com/amekala/ads-mcp](https://github.com/amekala/ads-mcp) |
|
|
215
|
-
| **Adspirer Docs** | Setup guides, platform docs, API reference | [adspirer.com/docs](https://www.adspirer.com/docs) |
|
|
216
|
-
| **MCP Server** | Production MCP endpoint (Streamable HTTP) | `https://mcp.adspirer.com/mcp` |
|
|
217
|
-
| **MCP Registry** | Model Context Protocol registry listing | [registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io) |
|
|
195
|
+
- **[Adspirer MCP server](https://mcp.adspirer.com/mcp)** — the canonical tool surface, consumed by ChatGPT Connectors, Claude Desktop, and Claude Code. For n8n agentic workflows, use [`n8n-nodes-mcp`](https://www.npmjs.com/package/n8n-nodes-mcp) pointed at this URL.
|
|
196
|
+
- **[REST API docs](https://www.adspirer.com/docs/api-reference/introduction)** — full endpoint reference, envelope, rate limits
|
|
197
|
+
- **[adspirer.com](https://adspirer.com)** — product overview
|
|
218
198
|
|
|
219
199
|
## Development
|
|
220
200
|
|
|
221
201
|
### Prerequisites
|
|
222
202
|
|
|
223
|
-
- Node.js 22 LTS (required — Node 25 has compatibility issues with `isolated-vm`)
|
|
203
|
+
- Node.js 22 LTS (required — Node 25 has compatibility issues with n8n-core's `isolated-vm` dependency)
|
|
224
204
|
- npm
|
|
225
205
|
|
|
226
206
|
### Setup
|
|
@@ -235,66 +215,56 @@ npm install
|
|
|
235
215
|
### Commands
|
|
236
216
|
|
|
237
217
|
```bash
|
|
238
|
-
npm run
|
|
218
|
+
npm run codegen # Regenerate operations from api.adspirer.ai/openapi.json
|
|
239
219
|
npm run build # Compile TypeScript → dist/
|
|
240
|
-
npm run lint #
|
|
241
|
-
npm run lint:fix #
|
|
220
|
+
npm run lint # n8n community-node lint (must pass for verification)
|
|
221
|
+
npm run lint:fix # Autofix lint issues
|
|
222
|
+
npm run dev # Local n8n on :5678 with this node hot-reloaded
|
|
242
223
|
npm run release # Bump version, tag, push → GH Action publishes to npm
|
|
243
224
|
```
|
|
244
225
|
|
|
245
|
-
###
|
|
226
|
+
### How operations are generated
|
|
246
227
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
228
|
+
`npm run codegen` fetches `https://api.adspirer.ai/openapi.json`, filters tool endpoints, and emits `nodes/Adspirer/generated/tools.ts` — a typed metadata array. `shared/build-properties.ts` then turns that metadata into n8n's `INodeProperties[]` at module load:
|
|
229
|
+
|
|
230
|
+
- One **Platform** dropdown (5 options)
|
|
231
|
+
- One **Operation** dropdown per platform, filtered by `displayOptions`
|
|
232
|
+
- One field per argument with the correct type (string / number / boolean / enum)
|
|
250
233
|
|
|
251
|
-
|
|
234
|
+
Tools whose arguments contain nested `array` or `object` types are skipped at codegen time with a `skipped` reason stored in the metadata. They still exist on the REST API — use the n8n HTTP Request node to call them.
|
|
252
235
|
|
|
253
|
-
|
|
236
|
+
Idempotency-Key logic reads `x-adspirer-read-only` from the OpenAPI spec per-tool, so non-read operations automatically send an idempotency header.
|
|
237
|
+
|
|
238
|
+
### Project structure
|
|
254
239
|
|
|
255
240
|
```
|
|
256
241
|
n8n-nodes-adspirer/
|
|
257
242
|
├── credentials/
|
|
258
|
-
│
|
|
259
|
-
|
|
260
|
-
├──
|
|
261
|
-
│
|
|
262
|
-
│
|
|
263
|
-
│
|
|
264
|
-
│
|
|
265
|
-
│
|
|
266
|
-
│
|
|
267
|
-
│
|
|
268
|
-
│
|
|
269
|
-
|
|
270
|
-
│
|
|
271
|
-
├──
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
├── package.json
|
|
276
|
-
├── tsconfig.json
|
|
277
|
-
└── eslint.config.mjs
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
### Publishing
|
|
281
|
-
|
|
282
|
-
Releases are published to npm via GitHub Actions with provenance attestation (required for n8n Creator Portal verification). The workflow triggers on semver tags:
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
npm run release # Interactive: bumps version, updates changelog, tags, pushes
|
|
243
|
+
│ └── AdspireApi.credentials.ts # API key Bearer auth, credential-test
|
|
244
|
+
├── nodes/Adspirer/
|
|
245
|
+
│ ├── Adspirer.node.ts # Main node — execute() loop, error mapping
|
|
246
|
+
│ ├── Adspirer.node.json # Codex metadata (categories, AI hints)
|
|
247
|
+
│ ├── generated/
|
|
248
|
+
│ │ └── tools.ts # GENERATED from OpenAPI, do not hand-edit
|
|
249
|
+
│ ├── shared/
|
|
250
|
+
│ │ ├── build-properties.ts # Turns TOOLS metadata → INodeProperties[]
|
|
251
|
+
│ │ ├── toolMapping.ts # resolveTool, buildToolArguments, isWriteTool
|
|
252
|
+
│ │ └── descriptions.ts # re-exports platformSelect
|
|
253
|
+
│ ├── adspirer.svg / .dark.svg # Node icons
|
|
254
|
+
├── scripts/
|
|
255
|
+
│ └── generate-operations.js # Codegen (fetch OpenAPI → emit tools.ts)
|
|
256
|
+
├── spec/
|
|
257
|
+
│ └── openapi.json # Cached spec for reproducible builds
|
|
258
|
+
├── icons/ # Credential-level icons
|
|
259
|
+
└── .github/workflows/ # CI + provenance-attested npm publish
|
|
286
260
|
```
|
|
287
261
|
|
|
288
|
-
The GitHub Action then builds, lints, and publishes to npm with OIDC provenance signing.
|
|
289
|
-
|
|
290
262
|
## Support
|
|
291
263
|
|
|
292
|
-
- **Email:** abhi@adspirer.com
|
|
293
|
-
- **Issues:** [github.com/amekala/n8n-nodes-adspirer/issues](https://github.com/amekala/n8n-nodes-adspirer/issues)
|
|
294
|
-
- **Adspirer Issues:** [github.com/amekala/ads-mcp/issues](https://github.com/amekala/ads-mcp/issues)
|
|
295
264
|
- **Website:** [adspirer.ai](https://adspirer.ai)
|
|
296
|
-
- **
|
|
297
|
-
- **
|
|
265
|
+
- **REST API docs:** [adspirer.com/docs/api-reference](https://www.adspirer.com/docs/api-reference/introduction)
|
|
266
|
+
- **Issues:** [github.com/amekala/n8n-nodes-adspirer/issues](https://github.com/amekala/n8n-nodes-adspirer/issues)
|
|
267
|
+
- **Email:** abhi@adspirer.com
|
|
298
268
|
|
|
299
269
|
## License
|
|
300
270
|
|
|
@@ -6,8 +6,8 @@ class AdspireApi {
|
|
|
6
6
|
this.name = 'adspireApi';
|
|
7
7
|
this.displayName = 'Adspirer API';
|
|
8
8
|
this.icon = { light: 'file:../icons/adspirer.svg', dark: 'file:../icons/adspirer.dark.svg' };
|
|
9
|
-
this.documentationUrl = 'https://www.adspirer.com/docs/
|
|
10
|
-
this.description = '
|
|
9
|
+
this.documentationUrl = 'https://www.adspirer.com/docs/api-reference/introduction';
|
|
10
|
+
this.description = 'Generate an API key at https://adspirer.ai/keys. Keys are prefixed sk_live_ — treat them as secrets.';
|
|
11
11
|
this.properties = [
|
|
12
12
|
{
|
|
13
13
|
displayName: 'API Key',
|
|
@@ -15,7 +15,9 @@ class AdspireApi {
|
|
|
15
15
|
type: 'string',
|
|
16
16
|
typeOptions: { password: true },
|
|
17
17
|
default: '',
|
|
18
|
-
|
|
18
|
+
placeholder: 'sk_live_...',
|
|
19
|
+
required: true,
|
|
20
|
+
description: 'Your Adspirer API key from https://adspirer.ai/keys',
|
|
19
21
|
},
|
|
20
22
|
];
|
|
21
23
|
this.authenticate = {
|
|
@@ -28,9 +30,10 @@ class AdspireApi {
|
|
|
28
30
|
};
|
|
29
31
|
this.test = {
|
|
30
32
|
request: {
|
|
31
|
-
baseURL: 'https://
|
|
32
|
-
url: '/api/v1/
|
|
33
|
-
method: '
|
|
33
|
+
baseURL: 'https://api.adspirer.ai',
|
|
34
|
+
url: '/api/v1/tools/list_connected_accounts/execute',
|
|
35
|
+
method: 'POST',
|
|
36
|
+
body: { arguments: {} },
|
|
34
37
|
},
|
|
35
38
|
};
|
|
36
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdspireApi.credentials.js","sourceRoot":"","sources":["../../credentials/AdspireApi.credentials.ts"],"names":[],"mappings":";;;AAQA,MAAa,UAAU;IAAvB;QACC,SAAI,GAAG,YAAY,CAAC;QAEpB,gBAAW,GAAG,cAAc,CAAC;QAE7B,SAAI,GAAS,EAAE,KAAK,EAAE,4BAA4B,EAAE,IAAI,EAAE,iCAAiC,EAAE,CAAC;QAE9F,qBAAgB,GAAG,
|
|
1
|
+
{"version":3,"file":"AdspireApi.credentials.js","sourceRoot":"","sources":["../../credentials/AdspireApi.credentials.ts"],"names":[],"mappings":";;;AAQA,MAAa,UAAU;IAAvB;QACC,SAAI,GAAG,YAAY,CAAC;QAEpB,gBAAW,GAAG,cAAc,CAAC;QAE7B,SAAI,GAAS,EAAE,KAAK,EAAE,4BAA4B,EAAE,IAAI,EAAE,iCAAiC,EAAE,CAAC;QAE9F,qBAAgB,GAAG,0DAA0D,CAAC;QAE9E,gBAAW,GACV,sGAAsG,CAAC;QAExG,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,aAAa;gBAC1B,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,qDAAqD;aAClE;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,aAAa,EAAE,kCAAkC;iBACjD;aACD;SACD,CAAC;QAEF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,yBAAyB;gBAClC,GAAG,EAAE,+CAA+C;gBACpD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;aACvB;SACD,CAAC;IACH,CAAC;CAAA;AA1CD,gCA0CC"}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import { type IExecuteFunctions, type INodeExecutionData, type INodeType, type INodeTypeDescription } from 'n8n-workflow';
|
|
1
|
+
import { type IExecuteFunctions, type INodeExecutionData, type INodeType, type INodeTypeDescription, type ISupplyDataFunctions, type SupplyData } from 'n8n-workflow';
|
|
2
2
|
export declare class Adspirer implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
4
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
/**
|
|
6
|
+
* AI Agent (LangChain) integration. n8n's ToolsAgent invokes supplyData()
|
|
7
|
+
* on every node wired into its `ai_tool` slot. We return a DynamicStructuredTool
|
|
8
|
+
* whose schema is derived from the tool metadata we generated from the REST
|
|
9
|
+
* OpenAPI spec — so the agent sees typed, described arguments and can call
|
|
10
|
+
* the tool without our node doing argument discovery at prompt time.
|
|
11
|
+
*/
|
|
12
|
+
supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData>;
|
|
5
13
|
}
|