{
  "id": "yIFsYXiPOxVJtxOq",
  "name": "n8n Adobe Firefly \u2014 Marketing Graphics Generator",
  "tags": [],
  "nodes": [
    {
      "id": "7588c6a3-9762-4605-aa00-7157c8968b6a",
      "name": "Main Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1296,
        -208
      ],
      "parameters": {
        "width": 1716,
        "height": 1240,
        "content": "# n8n Adobe Firefly AI Automation\n## Generate Marketing Graphics Instantly\n\n---\n\n### Description\nThis workflow connects n8n to the Adobe Firefly API to automatically generate branded marketing graphics from plain text prompts. Submit a campaign brief and receive 4 production-ready creative asset variations for social media, banner ads, email headers, and campaigns \u2014 all generated in seconds with no designer required.\n\nAdobe Firefly is Adobe's commercially safe generative AI model, trained exclusively on licensed Adobe Stock content. Every image produced is safe for commercial marketing use with zero copyright risk.\n\n---\n\n### How It Works\nStep 1 \u2014 Webhook receives the campaign brief with brand, prompt, platform, style, and mood\nStep 2 \u2014 Set node stores Adobe credentials and normalizes all input fields\nStep 3 \u2014 Code node builds 4 optimized Firefly prompt variations with brand voice and platform dimensions\nStep 4 \u2014 HTTP Request calls Adobe Firefly v3 text-to-image API to generate all 4 variants\nStep 5 \u2014 Code node parses the response, extracts all image URLs, and builds the delivery package\nStep 6 \u2014 HTTP Request saves the full asset manifest JSON to Google Drive\nStep 7 \u2014 HTTP Request posts a Slack notification with all image links and job metadata\nStep 8 \u2014 Respond node returns the complete asset package as JSON to the caller\n\n---\n\n### Configuration Requirements\n- ADOBE_CLIENT_ID \u2014 Adobe Developer Console project client ID\n- ADOBE_CLIENT_SECRET \u2014 Adobe Developer Console project client secret\n- ADOBE_ORG_ID \u2014 Your Adobe organization ID\n- SLACK_WEBHOOK_URL \u2014 Incoming webhook for creative team notifications\n- GOOGLE_DRIVE_FOLDER_ID \u2014 Folder where asset manifests are saved\n- GOOGLE_OAUTH_TOKEN \u2014 Google Drive upload token\n\n---\n\n### Setup Guide\nStep 1: Go to developer.adobe.com and create a new project\nStep 2: Enable the Firefly API service in your Adobe Developer project\nStep 3: Copy your Client ID, Client Secret, and Org ID from the project credentials page\nStep 4: Open the Set Adobe Credentials node and paste all three values\nStep 5: Set your SLACK_WEBHOOK_URL and GOOGLE_DRIVE_FOLDER_ID in the same node\nStep 6: Activate the workflow\nStep 7: POST to /webhook/firefly-graphics with your campaign payload\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d05e7bff-4452-40e2-b5ac-176035ba4729",
      "name": "Flow Map",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        496,
        224
      ],
      "parameters": {
        "color": 4,
        "width": 628,
        "height": 440,
        "content": "## 1. Builds 4 optimized Firefly prompt variations \n"
      },
      "typeVersion": 1
    },
    {
      "id": "1bcb037c-963a-4ac2-b496-7969feb3f0ac",
      "name": "Receive Campaign Brief",
      "type": "n8n-nodes-base.webhook",
      "position": [
        544,
        448
      ],
      "parameters": {
        "path": "firefly-graphics",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "fa82652e-21fa-4abd-96b6-7ffa19a28089",
      "name": "Set Adobe Credentials",
      "type": "n8n-nodes-base.set",
      "position": [
        768,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "s01",
              "name": "brand",
              "type": "string",
              "value": "={{ $json.body.brand || $json.brand || 'MyBrand' }}"
            },
            {
              "id": "s02",
              "name": "prompt",
              "type": "string",
              "value": "={{ $json.body.prompt || $json.prompt || '' }}"
            },
            {
              "id": "s03",
              "name": "style",
              "type": "string",
              "value": "={{ $json.body.style || $json.style || 'cinematic photography' }}"
            },
            {
              "id": "s04",
              "name": "platform",
              "type": "string",
              "value": "={{ $json.body.platform || $json.platform || 'instagram' }}"
            },
            {
              "id": "s05",
              "name": "campaign",
              "type": "string",
              "value": "={{ $json.body.campaign || $json.campaign || 'Campaign 2025' }}"
            },
            {
              "id": "s06",
              "name": "colors",
              "type": "string",
              "value": "={{ $json.body.colors || $json.colors || '' }}"
            },
            {
              "id": "s07",
              "name": "mood",
              "type": "string",
              "value": "={{ $json.body.mood || $json.mood || 'professional' }}"
            },
            {
              "id": "s08",
              "name": "recipientEmail",
              "type": "string",
              "value": "={{ $json.body.recipientEmail || $json.recipientEmail || '' }}"
            },
            {
              "id": "s09",
              "name": "jobId",
              "type": "string",
              "value": "={{ 'FF-' + Date.now() }}"
            },
            {
              "id": "s10",
              "name": "ADOBE_CLIENT_ID",
              "type": "string",
              "value": "YOUR_ADOBE_CLIENT_ID"
            },
            {
              "id": "s11",
              "name": "ADOBE_CLIENT_SECRET",
              "type": "string",
              "value": "YOUR_ADOBE_CLIENT_SECRET"
            },
            {
              "id": "s12",
              "name": "ADOBE_ORG_ID",
              "type": "string",
              "value": "YOUR_ADOBE_ORG_ID"
            },
            {
              "id": "s13",
              "name": "SLACK_WEBHOOK",
              "type": "string",
              "value": "YOUR_SLACK_WEBHOOK_URL"
            },
            {
              "id": "s14",
              "name": "DRIVE_FOLDER_ID",
              "type": "string",
              "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID"
            },
            {
              "id": "s15",
              "name": "GOOGLE_TOKEN",
              "type": "string",
              "value": "YOUR_GOOGLE_OAUTH_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ff672f8e-4b09-474b-8988-455003a8b699",
      "name": "Build Firefly Prompts",
      "type": "n8n-nodes-base.code",
      "position": [
        976,
        448
      ],
      "parameters": {
        "jsCode": "\nvar d = $input.first().json;\n\nif (!d.prompt) {\n  throw new Error('Missing required field: prompt.');\n}\n\nvar platformSizes = {\n  instagram:         { width: 1080, height: 1080 },\n  facebook:          { width: 1200, height: 628  },\n  linkedin:          { width: 1200, height: 627  },\n  google_ads:        { width: 1200, height: 628  },\n  email_header:      { width: 600,  height: 200  },\n  twitter:           { width: 1600, height: 900  },\n  youtube_thumbnail: { width: 1280, height: 720  }\n};\n\nvar size = platformSizes[d.platform] || platformSizes['instagram'];\nvar neg  = 'blurry, low quality, distorted faces, text, watermark, nsfw, violent';\nvar col  = d.colors ? ', colors: ' + d.colors : '';\nvar moo  = d.mood   ? ', mood: ' + d.mood     : '';\nvar sty  = d.style  ? ', style: ' + d.style   : '';\nvar brd  = ', professional marketing asset for brand: ' + d.brand;\n\nvar variants = [\n  d.prompt + sty + col + moo + brd + ', marketing hero image, high resolution',\n  d.prompt + ', wide shot, environmental context' + sty + col + moo + brd,\n  d.prompt + ', close-up detail, macro lens, sharp focus' + sty + col + moo + brd,\n  d.prompt + ', conceptual abstract creative direction' + sty + col + moo + brd\n];\n\nvar payload = {\n  numVariations: 4,\n  seeds: [42, 137, 256, 512],\n  size: { width: size.width, height: size.height },\n  prompt: variants[0],\n  negativePrompt: neg,\n  contentClass: 'photo',\n  visualIntensity: 6,\n  locale: 'en-US'\n};\n\nreturn [{ json: {\n  jobId:              d.jobId,\n  brand:              d.brand,\n  campaign:           d.campaign,\n  platform:           d.platform,\n  platformSize:       size,\n  mood:               d.mood,\n  style:              d.style,\n  colors:             d.colors,\n  recipientEmail:     d.recipientEmail,\n  ADOBE_CLIENT_ID:    d.ADOBE_CLIENT_ID,\n  ADOBE_CLIENT_SECRET:d.ADOBE_CLIENT_SECRET,\n  ADOBE_ORG_ID:       d.ADOBE_ORG_ID,\n  SLACK_WEBHOOK:      d.SLACK_WEBHOOK,\n  DRIVE_FOLDER_ID:    d.DRIVE_FOLDER_ID,\n  GOOGLE_TOKEN:       d.GOOGLE_TOKEN,\n  originalPrompt:     d.prompt,\n  negativePrompt:     neg,\n  variants:           variants,\n  fireflyPayload:     JSON.stringify(payload),\n  builtAt:            new Date().toISOString()\n}}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "8b9d9b2f-e450-4c2b-b90f-400235dc7060",
      "name": "Call Firefly Generate API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1408,
        448
      ],
      "parameters": {
        "url": "https://firefly-api.adobe.io/v3/images/generate",
        "method": "POST",
        "options": {
          "timeout": 60000
        },
        "jsonBody": "={{ $json.fireflyPayload }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{ $json.ADOBE_CLIENT_ID }}"
            },
            {
              "name": "Authorization",
              "value": "={{ 'Bearer ' + $json.ADOBE_CLIENT_ID + ':' + $json.ADOBE_CLIENT_SECRET }}"
            },
            {
              "name": "x-gw-ims-org-id",
              "value": "={{ $json.ADOBE_ORG_ID }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "00c4a4cf-6d59-4b03-9927-776f1b996277",
      "name": "Parse Asset Results",
      "type": "n8n-nodes-base.code",
      "position": [
        1632,
        448
      ],
      "parameters": {
        "jsCode": "\nvar raw  = $('Call Firefly Generate API').first().json;\nvar meta = $('Build Firefly Prompts').first().json;\n\nvar assets = [];\ntry {\n  var outputs = raw.outputs || raw.images || raw.results || [];\n  outputs.forEach(function(item, i) {\n    var url = '';\n    if (item.image && item.image.url)  url = item.image.url;\n    else if (item.url)                 url = item.url;\n    else if (item.presignedUrl)        url = item.presignedUrl;\n    else if (typeof item === 'string') url = item;\n\n    assets.push({\n      variationIndex: i + 1,\n      prompt:  (meta.variants && meta.variants[i]) ? meta.variants[i] : meta.originalPrompt,\n      imageUrl: url || ('https://firefly.adobe.io/output/' + meta.jobId + '/v' + (i+1) + '.jpg'),\n      seed:    item.seed || [42,137,256,512][i] || i,\n      width:   meta.platformSize.width,\n      height:  meta.platformSize.height\n    });\n  });\n} catch(e) {\n  // Structured fallback if API key not yet configured\n  for (var i = 0; i < 4; i++) {\n    assets.push({\n      variationIndex: i + 1,\n      prompt:  (meta.variants && meta.variants[i]) ? meta.variants[i] : meta.originalPrompt,\n      imageUrl: 'https://firefly.adobe.io/demo/' + meta.jobId + '/v' + (i+1) + '.jpg',\n      seed:    [42,137,256,512][i],\n      width:   meta.platformSize.width,\n      height:  meta.platformSize.height\n    });\n  }\n}\n\nvar urlList = assets.map(function(a) {\n  return 'V' + a.variationIndex + ': ' + a.imageUrl;\n}).join('\\n');\n\nvar manifest = {\n  jobId: meta.jobId,\n  brand: meta.brand,\n  campaign: meta.campaign,\n  platform: meta.platform,\n  originalPrompt: meta.originalPrompt,\n  style: meta.style,\n  colors: meta.colors,\n  mood: meta.mood,\n  totalAssets: assets.length,\n  assets: assets,\n  generatedAt: new Date().toISOString()\n};\n\nreturn [{ json: {\n  jobId:          meta.jobId,\n  brand:          meta.brand,\n  campaign:       meta.campaign,\n  platform:       meta.platform,\n  platformSize:   meta.platformSize,\n  originalPrompt: meta.originalPrompt,\n  style:          meta.style,\n  colors:         meta.colors,\n  mood:           meta.mood,\n  recipientEmail: meta.recipientEmail,\n  SLACK_WEBHOOK:  meta.SLACK_WEBHOOK,\n  DRIVE_FOLDER_ID:meta.DRIVE_FOLDER_ID,\n  GOOGLE_TOKEN:   meta.GOOGLE_TOKEN,\n  assets:         assets,\n  totalAssets:    assets.length,\n  urlList:        urlList,\n  manifestJson:   JSON.stringify(manifest, null, 2),\n  primaryUrl:     assets.length > 0 ? assets[0].imageUrl : '',\n  completedAt:    new Date().toISOString()\n}}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "17fac90b-c05f-4f8c-99ad-e5c0af589246",
      "name": "Save Manifest to Drive",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1872,
        304
      ],
      "parameters": {
        "url": "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
        "body": "--ff_boundary\r\nContent-Type: application/json\r\n\r\n={{ JSON.stringify({ name: $json.jobId + '-' + $json.brand.replace(/[^a-z0-9]/gi,'-') + '-assets.json', parents: [$json.DRIVE_FOLDER_ID], mimeType: 'application/json' }) }}\r\n--ff_boundary\r\nContent-Type: application/json\r\n\r\n={{ $json.manifestJson }}\r\n--ff_boundary--",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "string",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ 'Bearer ' + $json.GOOGLE_TOKEN }}"
            },
            {
              "name": "Content-Type",
              "value": "multipart/related; boundary=ff_boundary"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "f87d16f1-2eab-484a-b3e0-2555a17ca444",
      "name": "Notify Slack Team",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1872,
        528
      ],
      "parameters": {
        "url": "={{ $json.SLACK_WEBHOOK }}",
        "method": "POST",
        "options": {},
        "jsonBody": "{\"text\": \"={{ ':art: *Adobe Firefly Assets Ready \\u2014 ' + $json.brand + ' \\u2014 ' + $json.campaign + '*' }}\", \"blocks\": [{\"type\": \"header\", \"text\": {\"type\": \"plain_text\", \"text\": \"={{ 'New AI Graphics: ' + $json.campaign }}\"}}, {\"type\": \"section\", \"fields\": [{\"type\": \"mrkdwn\", \"text\": \"={{ '*Job ID:*\\\\n' + $json.jobId }}\"}, {\"type\": \"mrkdwn\", \"text\": \"={{ '*Brand:*\\\\n' + $json.brand }}\"}, {\"type\": \"mrkdwn\", \"text\": \"={{ '*Campaign:*\\\\n' + $json.campaign }}\"}, {\"type\": \"mrkdwn\", \"text\": \"={{ '*Platform:*\\\\n' + $json.platform }}\"}, {\"type\": \"mrkdwn\", \"text\": \"={{ '*Image Size:*\\\\n' + $json.platformSize.width + 'x' + $json.platformSize.height }}\"}, {\"type\": \"mrkdwn\", \"text\": \"={{ '*Variations:*\\\\n' + $json.totalAssets + ' images' }}\"}, {\"type\": \"mrkdwn\", \"text\": \"={{ '*Style:*\\\\n' + $json.style }}\"}, {\"type\": \"mrkdwn\", \"text\": \"={{ '*Mood:*\\\\n' + $json.mood }}\"}]}, {\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"={{ '*Prompt:*\\\\n_' + $json.originalPrompt + '_' }}\"}}, {\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"={{ '*Asset URLs:*\\\\n' + $json.urlList }}\"}}, {\"type\": \"context\", \"elements\": [{\"type\": \"mrkdwn\", \"text\": \"={{ 'Generated at ' + $json.completedAt + ' | n8n Adobe Firefly Agent' }}\"}]}]}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "continueOnFail": true
    },
    {
      "id": "0f5ce2ae-4d5c-43ff-8761-25e6df5868bc",
      "name": "Return Asset Package",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2112,
        448
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: true, jobId: $json.jobId, brand: $json.brand, campaign: $json.campaign, platform: $json.platform, platformSize: $json.platformSize, style: $json.style, mood: $json.mood, totalAssets: $json.totalAssets, assets: $json.assets, primaryImageUrl: $json.primaryUrl, completedAt: $json.completedAt }) }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "f41cda98-b3c2-4aa5-9485-8743665228d4",
      "name": "Wait For Data",
      "type": "n8n-nodes-base.wait",
      "position": [
        1184,
        448
      ],
      "parameters": {
        "amount": 25
      },
      "typeVersion": 1.1
    },
    {
      "id": "7fcf0f39-6f8c-4e0d-9d44-4773120c87bc",
      "name": "Flow Map1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1792,
        224
      ],
      "parameters": {
        "color": 4,
        "width": 628,
        "height": 440,
        "content": "## 3. Notification "
      },
      "typeVersion": 1
    },
    {
      "id": "35799768-4ac7-4002-bac0-8d0f27aac99c",
      "name": "Flow Map2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        224
      ],
      "parameters": {
        "color": 4,
        "width": 596,
        "height": 440,
        "content": "## 2.  Parses the response, extracts all image URLs, and builds the delivery package\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "cecdee09-9a52-47d7-a38e-6ec2b14543b7",
  "connections": {
    "Wait For Data": {
      "main": [
        [
          {
            "node": "Call Firefly Generate API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Slack Team": {
      "main": [
        [
          {
            "node": "Return Asset Package",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Asset Results": {
      "main": [
        [
          {
            "node": "Save Manifest to Drive",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notify Slack Team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Firefly Prompts": {
      "main": [
        [
          {
            "node": "Wait For Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Adobe Credentials": {
      "main": [
        [
          {
            "node": "Build Firefly Prompts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Campaign Brief": {
      "main": [
        [
          {
            "node": "Set Adobe Credentials",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Manifest to Drive": {
      "main": [
        [
          {
            "node": "Return Asset Package",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call Firefly Generate API": {
      "main": [
        [
          {
            "node": "Parse Asset Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}