@awesomate/hosting-mcp 0.12.0 → 0.13.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.
Files changed (58) hide show
  1. package/dist/index.js +204 -8
  2. package/package.json +2 -2
  3. package/skill/awesomate-app-builder/SKILL.md +5 -1
  4. package/skill/awesomate-credentials/SKILL.md +1 -1
  5. package/skill/awesomate-hosting/SKILL.md +50 -159
  6. package/skill/awesomate-hosting/references/connect-troubleshooting.md +77 -0
  7. package/skill/awesomate-hosting/references/multi-account.md +33 -0
  8. package/skill/awesomate-hosting/references/rest-fallback.md +30 -0
  9. package/skill/awesomate-hosting/scripts/bootstrap.mjs +27 -7
  10. package/skill/awesomate-n8n/SKILL.md +153 -147
  11. package/skill/awesomate-n8n/evals/ai-agent-build/graders/grader.md +31 -0
  12. package/skill/awesomate-n8n/evals/ai-agent-build/prompt.md +1 -0
  13. package/skill/awesomate-n8n/evals/build-form-email/graders/grader.md +30 -0
  14. package/skill/awesomate-n8n/evals/build-form-email/prompt.md +1 -0
  15. package/skill/awesomate-n8n/evals/datatable-dedupe/graders/grader.md +32 -0
  16. package/skill/awesomate-n8n/evals/datatable-dedupe/prompt.md +2 -0
  17. package/skill/awesomate-n8n/evals/diagnose-failure/graders/grader.md +27 -0
  18. package/skill/awesomate-n8n/evals/diagnose-failure/prompt.md +2 -0
  19. package/skill/awesomate-n8n/evals/essentials-upsell/graders/grader.md +27 -0
  20. package/skill/awesomate-n8n/evals/essentials-upsell/prompt.md +2 -0
  21. package/skill/awesomate-n8n/evals/live-change-promote/graders/grader.md +35 -0
  22. package/skill/awesomate-n8n/evals/live-change-promote/prompt.md +2 -0
  23. package/skill/awesomate-n8n/evals/possibilities-grounded/graders/grader.md +28 -0
  24. package/skill/awesomate-n8n/evals/possibilities-grounded/prompt.md +1 -0
  25. package/skill/awesomate-n8n/evals/validated-not-done/graders/grader.md +27 -0
  26. package/skill/awesomate-n8n/evals/validated-not-done/prompt.md +2 -0
  27. package/skill/awesomate-n8n/evals/vars-not-env/graders/grader.md +26 -0
  28. package/skill/awesomate-n8n/evals/vars-not-env/prompt.md +2 -0
  29. package/skill/awesomate-n8n/evals/webhook-body-fix/graders/grader.md +26 -0
  30. package/skill/awesomate-n8n/evals/webhook-body-fix/prompt.md +3 -0
  31. package/skill/awesomate-n8n/references/ai-agents.md +135 -0
  32. package/skill/awesomate-n8n/references/datatables.md +105 -0
  33. package/skill/awesomate-n8n/references/{node-recipes.md → platform-notes.md} +56 -7
  34. package/skill/awesomate-n8n/references/possibilities.md +83 -0
  35. package/skill/awesomate-n8n/references/testing-policy.md +115 -0
  36. package/skill/awesomate-n8n/references/troubleshooting.md +69 -0
  37. package/skill/awesomate-n8n/references/upgrade-loop.md +98 -0
  38. package/skill/awesomate-n8n/references/vendor/MANIFEST.json +26 -0
  39. package/skill/awesomate-n8n/references/vendor/code-node/BUILTIN_FUNCTIONS.md +779 -0
  40. package/skill/awesomate-n8n/references/vendor/code-node/COMMON_PATTERNS.md +1123 -0
  41. package/skill/awesomate-n8n/references/vendor/code-node/DATA_ACCESS.md +797 -0
  42. package/skill/awesomate-n8n/references/vendor/code-node/ERROR_PATTERNS.md +776 -0
  43. package/skill/awesomate-n8n/references/vendor/code-node/SKILL.md +703 -0
  44. package/skill/awesomate-n8n/references/vendor/expressions/COMMON_MISTAKES.md +406 -0
  45. package/skill/awesomate-n8n/references/vendor/expressions/EXAMPLES.md +496 -0
  46. package/skill/awesomate-n8n/references/vendor/expressions/SKILL.md +525 -0
  47. package/skill/awesomate-n8n/references/vendor/node-configuration/DEPENDENCIES.md +743 -0
  48. package/skill/awesomate-n8n/references/vendor/node-configuration/OPERATION_PATTERNS.md +926 -0
  49. package/skill/awesomate-n8n/references/vendor/node-configuration/SKILL.md +583 -0
  50. package/skill/awesomate-n8n/references/vendor/validation/ERROR_CATALOG.md +781 -0
  51. package/skill/awesomate-n8n/references/vendor/validation/FALSE_POSITIVES.md +695 -0
  52. package/skill/awesomate-n8n/references/vendor/validation/SKILL.md +414 -0
  53. package/skill/awesomate-n8n/references/vendor/workflow-patterns/SKILL.md +413 -0
  54. package/skill/awesomate-n8n/references/vendor/workflow-patterns/ai_agent_workflow.md +797 -0
  55. package/skill/awesomate-n8n/references/vendor/workflow-patterns/database_operations.md +798 -0
  56. package/skill/awesomate-n8n/references/vendor/workflow-patterns/http_api_integration.md +747 -0
  57. package/skill/awesomate-n8n/references/vendor/workflow-patterns/scheduled_tasks.md +786 -0
  58. package/skill/awesomate-n8n/references/vendor/workflow-patterns/webhook_processing.md +558 -0
@@ -0,0 +1,747 @@
1
+ <!--
2
+ VENDORED from n8n-builder@d293559 (n8n-workflow-patterns/http_api_integration.md) — DO NOT EDIT HERE.
3
+ Edit the source in ~/Projects/n8n-builder, then re-run:
4
+ node mcp/scripts/sync-n8n-references.mjs --write
5
+
6
+ Awesomate platform overrides — where this file conflicts with
7
+ ../platform-notes.md, platform-notes wins:
8
+ - $env is BLOCKED fleet-wide → use {{ $vars.key || 'fallback' }}
9
+ - Task runners are ON → no $helpers in Code nodes; use HTTP Request nodes
10
+ - Webhook payloads live at $json.body
11
+ - saveExecutionProgress must stay false
12
+ -->
13
+
14
+ # HTTP API Integration Pattern
15
+
16
+ **Use Case**: Fetch data from REST APIs, transform it, and use it in workflows.
17
+
18
+ ---
19
+
20
+ ## Pattern Structure
21
+
22
+ ```
23
+ Trigger → HTTP Request → [Transform] → [Action] → [Error Handler]
24
+ ```
25
+
26
+ **Key Characteristic**: External data fetching with error handling
27
+
28
+ ---
29
+
30
+ ## Core Components
31
+
32
+ ### 1. Trigger
33
+ **Options**:
34
+ - **Schedule** - Periodic fetching (most common)
35
+ - **Webhook** - Triggered by external event
36
+ - **Manual** - On-demand execution
37
+
38
+ ### 2. HTTP Request Node
39
+ **Purpose**: Call external REST APIs
40
+
41
+ **Configuration**:
42
+ ```javascript
43
+ {
44
+ method: "GET", // GET, POST, PUT, DELETE, PATCH
45
+ url: "https://api.example.com/users",
46
+ authentication: "predefinedCredentialType",
47
+ sendQuery: true,
48
+ queryParameters: {
49
+ "page": "={{$json.page}}",
50
+ "limit": "100"
51
+ },
52
+ sendHeaders: true,
53
+ headerParameters: {
54
+ "Accept": "application/json",
55
+ "X-API-Version": "v1"
56
+ }
57
+ }
58
+ ```
59
+
60
+ ### 3. Response Processing
61
+ **Purpose**: Extract and transform API response data
62
+
63
+ **Typical flow**:
64
+ ```
65
+ HTTP Request → Code (parse) → Set (map fields) → Action
66
+ ```
67
+
68
+ ### 4. Action
69
+ **Common actions**:
70
+ - Store in database
71
+ - Send to another API
72
+ - Create notifications
73
+ - Update spreadsheet
74
+
75
+ ### 5. Error Handler
76
+ **Purpose**: Handle API failures gracefully
77
+
78
+ **Error Trigger Workflow**:
79
+ ```
80
+ Error Trigger → Log Error → Notify Admin → Retry Logic (optional)
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Common Use Cases
86
+
87
+ ### 1. Data Fetching & Storage
88
+ **Flow**: Schedule → HTTP Request → Transform → Database
89
+
90
+ **Example** (Fetch GitHub issues):
91
+ ```
92
+ 1. Schedule (every hour)
93
+ 2. HTTP Request
94
+ - Method: GET
95
+ - URL: https://api.github.com/repos/owner/repo/issues
96
+ - Auth: Bearer Token
97
+ - Query: state=open
98
+ 3. Code (filter by labels)
99
+ 4. Set (map to database schema)
100
+ 5. Postgres (upsert issues)
101
+ ```
102
+
103
+ **Response Handling**:
104
+ ```javascript
105
+ // Code node - filter issues
106
+ const issues = $input.all();
107
+ return issues
108
+ .filter(item => item.json.labels.some(l => l.name === 'bug'))
109
+ .map(item => ({
110
+ json: {
111
+ id: item.json.id,
112
+ title: item.json.title,
113
+ created_at: item.json.created_at
114
+ }
115
+ }));
116
+ ```
117
+
118
+ ### 2. API to API Integration
119
+ **Flow**: Trigger → Fetch from API A → Transform → Send to API B
120
+
121
+ **Example** (Jira to Slack):
122
+ ```
123
+ 1. Schedule (every 15 minutes)
124
+ 2. HTTP Request (GET Jira tickets updated today)
125
+ 3. IF (check if tickets exist)
126
+ 4. Set (format for Slack)
127
+ 5. HTTP Request (POST to Slack webhook)
128
+ ```
129
+
130
+ ### 3. Data Enrichment
131
+ **Flow**: Trigger → Fetch base data → Call enrichment API → Combine → Store
132
+
133
+ **Example** (Enrich contacts with company data):
134
+ ```
135
+ 1. Postgres (SELECT new contacts)
136
+ 2. Code (extract company domains)
137
+ 3. HTTP Request (call Clearbit API for each domain)
138
+ 4. Set (combine contact + company data)
139
+ 5. Postgres (UPDATE contacts with enrichment)
140
+ ```
141
+
142
+ ### 4. Monitoring & Alerting
143
+ **Flow**: Schedule → Check API health → IF unhealthy → Alert
144
+
145
+ **Example** (API health check):
146
+ ```
147
+ 1. Schedule (every 5 minutes)
148
+ 2. HTTP Request (GET /health endpoint)
149
+ 3. IF (status !== 200 OR response time > 2000ms)
150
+ 4. Slack (alert #ops-team)
151
+ 5. PagerDuty (create incident)
152
+ ```
153
+
154
+ ### 5. Batch Processing
155
+ **Flow**: Trigger → Fetch large dataset → Split in Batches → Process → Loop
156
+
157
+ **Example** (Process all users):
158
+ ```
159
+ 1. Manual Trigger
160
+ 2. HTTP Request (GET /api/users?limit=1000)
161
+ 3. Split In Batches (100 items per batch)
162
+ 4. HTTP Request (POST /api/process for each batch)
163
+ 5. Wait (2 seconds between batches - rate limiting)
164
+ 6. Loop (back to step 4 until all processed)
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Authentication Methods
170
+
171
+ ### 1. None (Public APIs)
172
+ ```javascript
173
+ {
174
+ authentication: "none"
175
+ }
176
+ ```
177
+
178
+ ### 2. Bearer Token (Most Common)
179
+ **Setup**: Create credential
180
+ ```javascript
181
+ {
182
+ authentication: "predefinedCredentialType",
183
+ nodeCredentialType: "httpHeaderAuth",
184
+ headerAuth: {
185
+ name: "Authorization",
186
+ value: "Bearer YOUR_TOKEN"
187
+ }
188
+ }
189
+ ```
190
+
191
+ **Access in workflow**:
192
+ ```javascript
193
+ {
194
+ authentication: "predefinedCredentialType",
195
+ nodeCredentialType: "httpHeaderAuth"
196
+ }
197
+ ```
198
+
199
+ ### 3. API Key (Header or Query)
200
+ **Header auth**:
201
+ ```javascript
202
+ {
203
+ sendHeaders: true,
204
+ headerParameters: {
205
+ "X-API-Key": "={{$credentials.apiKey}}"
206
+ }
207
+ }
208
+ ```
209
+
210
+ **Query auth**:
211
+ ```javascript
212
+ {
213
+ sendQuery: true,
214
+ queryParameters: {
215
+ "api_key": "={{$credentials.apiKey}}"
216
+ }
217
+ }
218
+ ```
219
+
220
+ ### 4. Basic Auth
221
+ **Setup**: Create "Basic Auth" credential
222
+ ```javascript
223
+ {
224
+ authentication: "predefinedCredentialType",
225
+ nodeCredentialType: "httpBasicAuth"
226
+ }
227
+ ```
228
+
229
+ ### 5. OAuth2
230
+ **Setup**: Create OAuth2 credential with:
231
+ - Authorization URL
232
+ - Token URL
233
+ - Client ID
234
+ - Client Secret
235
+ - Scopes
236
+
237
+ ```javascript
238
+ {
239
+ authentication: "predefinedCredentialType",
240
+ nodeCredentialType: "oAuth2Api"
241
+ }
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Handling API Responses
247
+
248
+ ### Success Response (200-299)
249
+ **Default**: Data flows to next node
250
+
251
+ **Access response**:
252
+ ```javascript
253
+ // Entire response
254
+ {{$json}}
255
+
256
+ // Specific fields
257
+ {{$json.data.id}}
258
+ {{$json.results[0].name}}
259
+ ```
260
+
261
+ ### Pagination
262
+
263
+ #### Pattern 1: Offset-based
264
+ ```
265
+ 1. Set (initialize: page=1, has_more=true)
266
+ 2. HTTP Request (GET /api/items?page={{$json.page}})
267
+ 3. Code (check if more pages)
268
+ 4. IF (has_more === true)
269
+ └→ Set (increment page) → Loop to step 2
270
+ ```
271
+
272
+ **Code node** (check pagination):
273
+ ```javascript
274
+ const items = $input.first().json;
275
+ const currentPage = $json.page || 1;
276
+
277
+ return [{
278
+ json: {
279
+ items: items.results,
280
+ page: currentPage + 1,
281
+ has_more: items.next !== null
282
+ }
283
+ }];
284
+ ```
285
+
286
+ #### Pattern 2: Cursor-based
287
+ ```
288
+ 1. HTTP Request (GET /api/items)
289
+ 2. Code (extract next_cursor)
290
+ 3. IF (next_cursor exists)
291
+ └→ Set (cursor={{$json.next_cursor}}) → Loop to step 1
292
+ ```
293
+
294
+ #### Pattern 3: Link Header
295
+ ```javascript
296
+ // Code node - parse Link header
297
+ const linkHeader = $input.first().json.headers['link'];
298
+ const hasNext = linkHeader && linkHeader.includes('rel="next"');
299
+
300
+ return [{
301
+ json: {
302
+ items: $input.first().json.body,
303
+ has_next: hasNext,
304
+ next_url: hasNext ? parseNextUrl(linkHeader) : null
305
+ }
306
+ }];
307
+ ```
308
+
309
+ ### Error Responses (400-599)
310
+
311
+ **Configure HTTP Request**:
312
+ ```javascript
313
+ {
314
+ continueOnFail: true, // Don't stop workflow on error
315
+ ignoreResponseCode: true // Get response even on error
316
+ }
317
+ ```
318
+
319
+ **Handle errors**:
320
+ ```
321
+ HTTP Request (continueOnFail: true)
322
+ → IF (check error)
323
+ ├─ [Success Path]
324
+ └─ [Error Path] → Log → Retry or Alert
325
+ ```
326
+
327
+ **IF condition**:
328
+ ```javascript
329
+ {{$json.error}} is empty
330
+ // OR
331
+ {{$json.statusCode}} < 400
332
+ ```
333
+
334
+ ---
335
+
336
+ ## Rate Limiting
337
+
338
+ ### Pattern 1: Wait Between Requests
339
+ ```
340
+ Split In Batches (1 item per batch)
341
+ → HTTP Request
342
+ → Wait (1 second)
343
+ → Loop
344
+ ```
345
+
346
+ ### Pattern 2: Exponential Backoff
347
+ ```javascript
348
+ // Code node
349
+ const maxRetries = 3;
350
+ let retryCount = $json.retryCount || 0;
351
+
352
+ if ($json.error && retryCount < maxRetries) {
353
+ const delay = Math.pow(2, retryCount) * 1000; // 1s, 2s, 4s
354
+
355
+ return [{
356
+ json: {
357
+ ...$json,
358
+ retryCount: retryCount + 1,
359
+ waitTime: delay
360
+ }
361
+ }];
362
+ }
363
+ ```
364
+
365
+ ### Pattern 3: Respect Rate Limit Headers
366
+ ```javascript
367
+ // Code node - check rate limit
368
+ const headers = $input.first().json.headers;
369
+ const remaining = parseInt(headers['x-ratelimit-remaining'] || '999');
370
+ const resetTime = parseInt(headers['x-ratelimit-reset'] || '0');
371
+
372
+ if (remaining < 10) {
373
+ const now = Math.floor(Date.now() / 1000);
374
+ const waitSeconds = resetTime - now;
375
+
376
+ return [{
377
+ json: {
378
+ shouldWait: true,
379
+ waitSeconds: Math.max(waitSeconds, 0)
380
+ }
381
+ }];
382
+ }
383
+
384
+ return [{ json: { shouldWait: false } }];
385
+ ```
386
+
387
+ ---
388
+
389
+ ## Request Configuration
390
+
391
+ ### GET Request
392
+ ```javascript
393
+ {
394
+ method: "GET",
395
+ url: "https://api.example.com/users",
396
+ sendQuery: true,
397
+ queryParameters: {
398
+ "page": "1",
399
+ "limit": "100",
400
+ "filter": "active"
401
+ }
402
+ }
403
+ ```
404
+
405
+ ### POST Request (JSON Body)
406
+ ```javascript
407
+ {
408
+ method: "POST",
409
+ url: "https://api.example.com/users",
410
+ sendBody: true,
411
+ bodyParametersJson: JSON.stringify({
412
+ name: "={{$json.name}}",
413
+ email: "={{$json.email}}",
414
+ role: "user"
415
+ })
416
+ }
417
+ ```
418
+
419
+ ### POST Request (Form Data)
420
+ ```javascript
421
+ {
422
+ method: "POST",
423
+ url: "https://api.example.com/upload",
424
+ sendBody: true,
425
+ bodyParametersUi: {
426
+ parameter: [
427
+ { name: "file", value: "={{$json.fileData}}" },
428
+ { name: "filename", value: "={{$json.filename}}" }
429
+ ]
430
+ },
431
+ sendHeaders: true,
432
+ headerParameters: {
433
+ "Content-Type": "multipart/form-data"
434
+ }
435
+ }
436
+ ```
437
+
438
+ ### PUT/PATCH Request (Update)
439
+ ```javascript
440
+ {
441
+ method: "PATCH",
442
+ url: "https://api.example.com/users/={{$json.userId}}",
443
+ sendBody: true,
444
+ bodyParametersJson: JSON.stringify({
445
+ status: "active",
446
+ last_updated: "={{$now}}"
447
+ })
448
+ }
449
+ ```
450
+
451
+ ### DELETE Request
452
+ ```javascript
453
+ {
454
+ method: "DELETE",
455
+ url: "https://api.example.com/users/={{$json.userId}}"
456
+ }
457
+ ```
458
+
459
+ ---
460
+
461
+ ## Error Handling Patterns
462
+
463
+ ### Pattern 1: Retry on Failure
464
+ ```
465
+ HTTP Request (continueOnFail: true)
466
+ → IF (error occurred)
467
+ └→ Wait (5 seconds)
468
+ └→ HTTP Request (retry)
469
+ ```
470
+
471
+ ### Pattern 2: Fallback API
472
+ ```
473
+ HTTP Request (Primary API, continueOnFail: true)
474
+ → IF (failed)
475
+ └→ HTTP Request (Fallback API)
476
+ ```
477
+
478
+ ### Pattern 3: Error Trigger Workflow
479
+ **Main Workflow**:
480
+ ```
481
+ HTTP Request → Process Data
482
+ ```
483
+
484
+ **Error Workflow**:
485
+ ```
486
+ Error Trigger
487
+ → Set (extract error details)
488
+ → Slack (alert team)
489
+ → Database (log error for analysis)
490
+ ```
491
+
492
+ ### Pattern 4: Circuit Breaker
493
+ ```javascript
494
+ // Code node - circuit breaker logic
495
+ const failures = $json.recentFailures || 0;
496
+ const threshold = 5;
497
+
498
+ if (failures >= threshold) {
499
+ throw new Error('Circuit breaker open - too many failures');
500
+ }
501
+
502
+ return [{ json: { canProceed: true } }];
503
+ ```
504
+
505
+ ---
506
+
507
+ ## Response Transformation
508
+
509
+ ### Extract Nested Data
510
+ ```javascript
511
+ // Code node
512
+ const response = $input.first().json;
513
+
514
+ return response.data.items.map(item => ({
515
+ json: {
516
+ id: item.id,
517
+ name: item.attributes.name,
518
+ email: item.attributes.contact.email
519
+ }
520
+ }));
521
+ ```
522
+
523
+ ### Flatten Arrays
524
+ ```javascript
525
+ // Code node - flatten nested array
526
+ const items = $input.all();
527
+ const flattened = items.flatMap(item =>
528
+ item.json.results.map(result => ({
529
+ json: {
530
+ parent_id: item.json.id,
531
+ ...result
532
+ }
533
+ }))
534
+ );
535
+
536
+ return flattened;
537
+ ```
538
+
539
+ ### Combine Multiple API Responses
540
+ ```
541
+ HTTP Request 1 (users)
542
+ → Set (store users)
543
+ → HTTP Request 2 (orders for each user)
544
+ → Merge (combine users + orders)
545
+ ```
546
+
547
+ ---
548
+
549
+ ## Testing & Debugging
550
+
551
+ ### 1. Test with Manual Trigger
552
+ Replace Schedule with Manual Trigger for testing
553
+
554
+ ### 2. Use Postman/Insomnia First
555
+ - Test API outside n8n
556
+ - Understand response structure
557
+ - Verify authentication
558
+
559
+ ### 3. Log Responses
560
+ ```javascript
561
+ // Code node - log for debugging
562
+ console.log('API Response:', JSON.stringify($input.first().json, null, 2));
563
+ return $input.all();
564
+ ```
565
+
566
+ ### 4. Check Execution Data
567
+ - View node output in n8n UI
568
+ - Check headers, body, status code
569
+ - Verify data structure
570
+
571
+ ### 5. Use Binary Data Properly
572
+ For file downloads:
573
+ ```javascript
574
+ {
575
+ method: "GET",
576
+ url: "https://api.example.com/download/file.pdf",
577
+ responseFormat: "file", // Important for binary data
578
+ outputPropertyName: "data"
579
+ }
580
+ ```
581
+
582
+ ---
583
+
584
+ ## Performance Optimization
585
+
586
+ ### 1. Parallel Requests
587
+ Use **Split In Batches** with multiple items:
588
+ ```
589
+ Set (create array of IDs)
590
+ → Split In Batches (10 items per batch)
591
+ → HTTP Request (processes all 10 in parallel)
592
+ → Loop
593
+ ```
594
+
595
+ ### 2. Caching
596
+ ```
597
+ IF (check cache exists)
598
+ ├─ [Cache Hit] → Use cached data
599
+ └─ [Cache Miss] → HTTP Request → Store in cache
600
+ ```
601
+
602
+ ### 3. Conditional Fetching
603
+ Only fetch if data changed:
604
+ ```
605
+ HTTP Request (GET with If-Modified-Since header)
606
+ → IF (status === 304)
607
+ └─ Use existing data
608
+ → IF (status === 200)
609
+ └─ Process new data
610
+ ```
611
+
612
+ ### 4. Batch API Calls
613
+ If API supports batch operations:
614
+ ```javascript
615
+ {
616
+ method: "POST",
617
+ url: "https://api.example.com/batch",
618
+ bodyParametersJson: JSON.stringify({
619
+ requests: $json.items.map(item => ({
620
+ method: "GET",
621
+ url: `/users/${item.id}`
622
+ }))
623
+ })
624
+ }
625
+ ```
626
+
627
+ ---
628
+
629
+ ## Common Gotchas
630
+
631
+ ### 1. ❌ Wrong: Hardcoded URLs
632
+ ```javascript
633
+ url: "https://api.example.com/prod/users"
634
+ ```
635
+
636
+ ### ✅ Correct: Use environment variables
637
+ ```javascript
638
+ url: "={{$env.API_BASE_URL}}/users"
639
+ ```
640
+
641
+ ### 2. ❌ Wrong: Credentials in parameters
642
+ ```javascript
643
+ headerParameters: {
644
+ "Authorization": "Bearer sk-abc123xyz" // ❌ Exposed!
645
+ }
646
+ ```
647
+
648
+ ### ✅ Correct: Use credentials system
649
+ ```javascript
650
+ authentication: "predefinedCredentialType",
651
+ nodeCredentialType: "httpHeaderAuth"
652
+ ```
653
+
654
+ ### 3. ❌ Wrong: No error handling
655
+ ```javascript
656
+ HTTP Request → Process (fails if API down)
657
+ ```
658
+
659
+ ### ✅ Correct: Handle errors
660
+ ```javascript
661
+ HTTP Request (continueOnFail: true) → IF (error) → Handle
662
+ ```
663
+
664
+ ### 4. ❌ Wrong: Blocking on large responses
665
+ Processing 10,000 items synchronously
666
+
667
+ ### ✅ Correct: Use batching
668
+ ```
669
+ Split In Batches (100 items) → Process → Loop
670
+ ```
671
+
672
+ ---
673
+
674
+ ## Real Template Examples
675
+
676
+ From n8n template library (892 API integration templates):
677
+
678
+ **GitHub to Notion**:
679
+ ```
680
+ Schedule → HTTP Request (GitHub API) → Transform → HTTP Request (Notion API)
681
+ ```
682
+
683
+ **Weather to Slack**:
684
+ ```
685
+ Schedule → HTTP Request (Weather API) → Set (format) → Slack
686
+ ```
687
+
688
+ **CRM Sync**:
689
+ ```
690
+ Schedule → HTTP Request (CRM A) → Transform → HTTP Request (CRM B)
691
+ ```
692
+
693
+ Browse the n8n template library (n8n.io/workflows) for more examples!
694
+
695
+ ---
696
+
697
+ ## Checklist for API Integration
698
+
699
+ ### Planning
700
+ - [ ] Test API with Postman/curl first
701
+ - [ ] Understand response structure
702
+ - [ ] Check rate limits
703
+ - [ ] Review authentication method
704
+ - [ ] Plan error handling
705
+
706
+ ### Implementation
707
+ - [ ] Use credentials (never hardcode)
708
+ - [ ] Configure proper HTTP method
709
+ - [ ] Set correct headers (Content-Type, Accept)
710
+ - [ ] Handle pagination if needed
711
+ - [ ] Add query parameters properly
712
+
713
+ ### Error Handling
714
+ - [ ] Set continueOnFail: true if needed
715
+ - [ ] Check response status codes
716
+ - [ ] Implement retry logic
717
+ - [ ] Add Error Trigger workflow
718
+ - [ ] Alert on failures
719
+
720
+ ### Performance
721
+ - [ ] Use batching for large datasets
722
+ - [ ] Add rate limiting if needed
723
+ - [ ] Consider caching
724
+ - [ ] Test with production load
725
+
726
+ ### Security
727
+ - [ ] Use HTTPS only
728
+ - [ ] Store secrets in credentials
729
+ - [ ] Validate API responses
730
+ - [ ] Use environment variables
731
+
732
+ ---
733
+
734
+ ## Summary
735
+
736
+ **Key Points**:
737
+ 1. **Authentication** via credentials system (never hardcode)
738
+ 2. **Error handling** is critical (continueOnFail + IF checks)
739
+ 3. **Pagination** for large datasets
740
+ 4. **Rate limiting** to respect API limits
741
+ 5. **Transform responses** to match your needs
742
+
743
+ **Pattern**: Trigger → HTTP Request → Transform → Action → Error Handler
744
+
745
+ **Related**:
746
+ - [webhook_processing.md](webhook_processing.md) - Receiving HTTP requests
747
+ - [database_operations.md](database_operations.md) - Storing API data