n8n
Build powerful content optimization workflows with Soke and n8n — includes downloadable workflow templates.
n8n Integration
Use Soke with n8n to build visual content optimization workflows. This guide covers credential setup, working with Soke's API response format, and includes ready-to-import workflow templates for every major Soke feature.
What you can build
- Keyword research pipelines — automatically research keywords on a schedule and push results to Google Sheets, Notion, or Airtable
- Content optimization workflows — chain keyword research → title optimization → description generation into a single automated pipeline
- Async job monitoring — generate thumbnails or transcribe videos with automatic polling until completion
- Chat-powered automation — use Soke's OpenAI-compatible chat endpoint to handle complex, multi-step content tasks in a single request
Prerequisites
- n8n — self-hosted or n8n Cloud
- Soke API key — get one from your Soke dashboard
Credential Setup
Create a Header Auth credential
In your n8n instance:
- Go to Settings → Credentials → Add Credential
- Search for Header Auth and select it
- Configure the fields:
- Name:
Soke API - Header Name:
X-Soke-Key - Header Value: your API key (e.g.,
sk_live_abc123...)
- Name:
- Click Save
This credential will be reused across all Soke workflow nodes.
Test the credential
Add an HTTP Request node to any workflow:
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/research/keywords - Authentication: Header Auth → select Soke API
- Body Content Type: JSON
- Body:
{
"topic": "test",
"platform": "youtube"
}Click Test step. If you see a response with "success": true, your credential is working.
Understanding Soke Responses in n8n
Every Soke API response follows a standard envelope:
{
"success": true,
"data": { /* endpoint-specific results */ },
"meta": {
"platform": "youtube",
"request_id": "uuid",
"processing_time_ms": 142
}
}Accessing data in expressions
In n8n expressions, access nested response fields like this:
| What you need | Expression |
|---|---|
| Full keywords array | {{ $json.data.keywords }} |
| First keyword name | {{ $json.data.keywords[0].keyword }} |
| Success check | {{ $json.success }} |
| Processing time | {{ $json.meta.processing_time_ms }} |
| All keyword names as array | {{ $json.data.keywords.map(k => k.keyword) }} |
Error handling
Always check the success field before processing results. Add an IF node after each HTTP Request:
- Condition:
{{ $json.success }}equalstrue - True branch: continue processing
- False branch: log
{{ $json.error.code }}and{{ $json.error.message }}
Workflow: Keyword Research
Research keywords for any topic and extract structured results.
Add a Manual Trigger
Start with a Manual Trigger node (or a Schedule Trigger for automated runs).
Add an HTTP Request node
Configure the node:
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/research/keywords - Authentication: Header Auth → Soke API
- Body Content Type: JSON
- Body:
{
"topic": "productivity tips for developers",
"platform": "youtube",
"maxResults": 20
}Use n8n expressions to make the topic dynamic: {{ $json.topic }} from a previous node, or {{ $('Trigger').item.json.topic }} to reference a specific upstream node.
Extract results with a Set node
Add a Set node to extract the fields you need:
- Mode: Raw JSON
- JSON Output:
{
"keywords": "{{ $json.data.keywords.map(k => k.keyword) }}",
"topKeyword": "{{ $json.data.keywords[0]?.keyword }}",
"keywordsWithScores": "{{ $json.data.keywords.slice(0, 5).map(k => ({ keyword: k.keyword, score: k.competitionScore, trend: k.trendDirection })) }}",
"longTailPhrases": "{{ $json.data.longTailPhrases }}"
}Workflow: Content Optimization Pipeline
Chain multiple Soke endpoints to go from a topic to fully optimized content in one workflow.
Pipeline flow: Keyword Research → Title Optimization → Description Generation
Total credits: 8 per run (2 + 3 + 3)
1. Research Keywords
HTTP Request node:
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/research/keywords - Body:
{
"topic": "{{ $json.topic }}",
"platform": "youtube",
"maxResults": 10
}2. Optimize Title
Add a second HTTP Request node. Reference keywords from step 1:
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/content/optimize-title - Body:
{
"draftTitle": "{{ $json.draftTitle || 'How to boost productivity as a developer' }}",
"platform": "youtube",
"keywords": "{{ $('1. Research Keywords').item.json.data.keywords.slice(0, 5).map(k => k.keyword) }}",
"keywordsWithScores": "{{ $('1. Research Keywords').item.json.data.keywords.slice(0, 5).map(k => ({ keyword: k.keyword, competitionScore: k.competitionScore, trendDirection: k.trendDirection })) }}"
}This passes the top 5 keywords with their scores to the title optimizer for better results.
3. Generate Description
Third HTTP Request node. Uses the best optimized title:
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/content/generate-description - Body:
{
"title": "{{ $json.data.alternatives[0]?.title }}",
"platform": "youtube",
"keywords": "{{ $('1. Research Keywords').item.json.data.keywords.slice(0, 5).map(k => k.keyword) }}",
"niche": "tech",
"tone": "casual"
}4. Combine Results
Add a Set node to merge everything into one output:
{
"optimizedTitle": "{{ $('2. Optimize Title').item.json.data.alternatives[0]?.title }}",
"titleScore": "{{ $('2. Optimize Title').item.json.data.alternatives[0]?.overallScore }}",
"description": "{{ $json.data.description }}",
"keywords": "{{ $('1. Research Keywords').item.json.data.keywords.slice(0, 5).map(k => k.keyword) }}",
"creditsUsed": 8
}From here, send the output to Google Sheets, Notion, Slack, or any other n8n integration.
Workflow: Content Scoring
Score a title or caption to see how well it's optimized.
Configure an HTTP Request node:
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/content/score - Body:
{
"content": "10 Developer Productivity Hacks That Actually Work",
"platform": "youtube",
"targetKeywords": ["developer productivity", "coding tips"]
}The response includes an overallScore (0–100) and a breakdown object with individual scores for keyword placement, emotional pull, curiosity gap, hook strength, and more. Each dimension includes a suggestion field when improvement is possible.
Key expressions for downstream nodes:
| Field | Expression |
|---|---|
| Overall score | {{ $json.data.overallScore }} |
| Keyword placement score | {{ $json.data.breakdown.keywordPlacement.value }} |
| All suggestions | {{ Object.entries($json.data.breakdown).filter(([k,v]) => v.suggestion).map(([k,v]) => v.suggestion) }} |
Workflow: Async Operations (Thumbnails & Transcription)
Thumbnail generation and transcription are async operations — they return immediately with a job ID, and you poll for results. Here's the pattern:
The polling loop pattern
Start Job → Wait → Poll Status → Is Completed?
├─ Yes → Process Results
└─ No → Wait & Retry (loops back to Poll)1. Start the job
Thumbnail generation:
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/thumbnail/generate - Body:
Using a template (recommended — create one in the Soke dashboard for consistent styling):
{
"manualTitle": "10 Developer Productivity Hacks",
"manualPrompt": "A developer at a clean desk with multiple monitors showing code",
"templateId": "your-template-id",
"platform": "youtube"
}Or without a template (all parameters required). Supported resolutions: 1280x720 (landscape) or 1080x1920 (portrait/shorts):
{
"manualTitle": "10 Developer Productivity Hacks",
"manualPrompt": "A developer at a clean desk with multiple monitors showing code",
"colorGrading": "Cinematic",
"layoutType": "TextCenter",
"resolution": "1280x720",
"platform": "youtube"
}Transcription:
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/transcription - Content Type: multipart/form-data
- Form field:
url=https://youtube.com/watch?v=VIDEO_ID
2. Add a Wait node
- Resume: After time interval
- Wait time: 5 seconds (thumbnails) or 10 seconds (transcription)
This gives the server time to start processing before your first poll.
3. Poll for status
Add an HTTP Request node:
Thumbnail:
- Method: GET
- URL:
https://api.usesoke.ai/api/v1/thumbnail/{{ $('Start Thumbnail').item.json.data.id }}
Transcription:
- Method: GET
- URL:
https://api.usesoke.ai/api/v1/transcription/{{ $('Start Transcription').item.json.data.id }}
4. Check completion with an IF node
- Condition:
{{ $json.data.status }}equalsCompleted(thumbnails) orcompleted(transcription) - True branch → process the results
- False branch → add another Wait node (5–10s), then loop back to the poll node
Set a maximum number of retries to avoid infinite loops. In the "Wait & Retry" branch, add an IF node that checks {{ $runIndex }} and stops after 20 iterations (approximately 100 seconds for thumbnails or 200 seconds for transcription).
Workflow: Chat Completions
Use Soke's OpenAI-compatible chat endpoint for natural language content tasks. The chat endpoint automatically orchestrates multiple services (keyword research, title optimization, etc.) based on your prompt.
- Method: POST
- URL:
https://api.usesoke.ai/api/v1/chat/completions - Body:
{
"messages": [
{
"role": "user",
"content": "Research keywords for cooking tutorials and suggest 3 optimized titles"
}
],
"platform": "youtube",
"model": "soke-v1",
"stream": false
}Response structure:
| Field | Expression | Description |
|---|---|---|
| AI response text | {{ $json.choices[0].message.content }} | Natural language synthesis |
| Services called | {{ $json.choices[0].message.data.services_used }} | Array of services used |
| Raw results | {{ $json.choices[0].message.data.results }} | Structured data from each service |
The chat endpoint costs 5 credits per request but can orchestrate multiple services in a single call. Compare this to running keyword research (2) + title optimization (3) = 5 credits for two separate calls — the chat endpoint gives you the same results plus a natural language summary.
Downloadable Workflows
Import these directly into n8n via Workflow → Import from File.
After importing, you'll need to update the credential: open any HTTP Request node, click the credential dropdown, and select your Soke API Header Auth credential.
| Workflow | Description | Credits | Download |
|---|---|---|---|
| Keyword Research | Research keywords for a topic and extract top results | 2 | keyword-research.json |
| Content Research | Find trending videos for given keywords | 2 | content-research.json |
| Content Pipeline | Keywords → Title → Description in one pipeline | 8 | content-pipeline.json |
| Title Scoring | Score a title with detailed breakdown | 2 | title-scoring.json |
| Chat Completions | Natural language content tasks via chat | 5 | chat-completions.json |
| Thumbnail Generation | Generate thumbnails with async polling | 4 | thumbnail-generation.json |
| Transcription | Transcribe videos with async polling | 1 | transcription.json |
Error Handling & Tips
Rate limit handling
If you hit a rate limit (429 status), the response includes a Retry-After header. Add an error handling branch:
- After each HTTP Request node, check
{{ $json.success }} - If
falseand{{ $json.error.code }}isRATE_LIMIT_EXCEEDED, add a Wait node for{{ $json.error.details.retryAfter }}seconds - Then retry the request
Credit monitoring
Add a credit check at the start of expensive workflows:
GET https://api.usesoke.ai/api/v1/credits/balanceUse an IF node to check {{ $json.data.currentBalance }} is sufficient before proceeding.
Common pitfalls
- Missing
platformfield — most endpoints default to"youtube", but it's best to always include it explicitly - Async polling too fast — don't poll more frequently than every 3 seconds. The downloadable workflows use 5–10 second intervals
- Large topic strings — the
topicfield has a 200-character limit. Use concise, keyword-focused topics - Expression syntax — n8n expressions use
{{ }}double braces. For complex JavaScript, use{{ }}with standard JS inside (e.g.,{{ $json.data.keywords.map(k => k.keyword).join(', ') }})
Scheduling workflows
Replace the Manual Trigger with a Schedule Trigger for automated runs:
- Daily keyword research — run once per day to track keyword trends
- Weekly competitor monitoring — check competitor channels weekly
- Hourly trend scanning — catch trending topics early
Monitor your credit usage when scheduling workflows. A content pipeline running daily uses 8 credits/day = ~240 credits/month. Check your plan's limits on the Rate Limiting & Credits page.