{
  "name": "TokPortal - Preview one US account order (no purchase)",
  "nodes": [
    {
      "id": "preview-note",
      "name": "Read before running",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        180,
        -260
      ],
      "parameters": {
        "content": "## Preview one US TikTok account order\nManual run only. Select an n8n Header Auth credential (X-API-Key) in all three HTTP Request nodes. Read + write scope is needed even for a POST simulation.\n\nThe POST always sends X-TokPortal-Dry-Run: true. No order, upload, publish, webhook, schedule or notification is created. Final output is a quote, not delivery. Never reuse its synthetic ID in a live workflow.",
        "height": 230,
        "width": 860
      }
    },
    {
      "id": "preview-start",
      "name": "Run preview manually",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        160,
        100
      ],
      "parameters": {}
    },
    {
      "id": "preview-countries",
      "name": "Read markets",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        390,
        100
      ],
      "parameters": {
        "method": "GET",
        "url": "https://app.tokportal.com/api/ext/countries",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "responseFormat": "json",
              "neverError": false
            }
          },
          "timeout": 30000
        }
      }
    },
    {
      "id": "preview-market-check",
      "name": "Confirm US availability",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        620,
        100
      ],
      "parameters": {
        "jsCode": "const response = $input.first().json;\nif (!Number.isInteger(response.statusCode) || response.statusCode < 200 || response.statusCode >= 300 || !Array.isArray(response.body?.data)) {\n  throw new Error('Could not read countries. Stop; do not simulate or choose another country.');\n}\nconst market = response.body.data.find(country => country.code === 'USA');\nif (!market) {\n  throw new Error('USA is not currently available for new accounts. Stop; videos_only_countries is not a new-account market list.');\n}\nreturn [{ json: { country: market.code, market_name: market.name } }];"
      }
    },
    {
      "id": "preview-costs",
      "name": "Read workspace costs",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        850,
        100
      ],
      "parameters": {
        "method": "GET",
        "url": "https://app.tokportal.com/api/ext/credit-costs",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "responseFormat": "json",
              "neverError": false
            }
          },
          "timeout": 30000
        }
      }
    },
    {
      "id": "preview-order",
      "name": "Simulate one account",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1080,
        100
      ],
      "parameters": {
        "method": "POST",
        "url": "https://app.tokportal.com/api/ext/bundles",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "responseFormat": "json",
              "neverError": false
            }
          },
          "timeout": 30000
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-TokPortal-Dry-Run",
              "value": "true"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "{\"bundle_type\": \"account_only\", \"platform\": \"tiktok\", \"country\": \"USA\", \"title\": \"US launch preview\", \"wants_advanced_warming\": false}"
      }
    },
    {
      "id": "preview-check",
      "name": "Verify preview and show quote",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1310,
        100
      ],
      "parameters": {
        "jsCode": "const response = $input.first().json;\nconst body = response.body;\nconst marker = Object.entries(response.headers || {}).find(([name]) => name.toLowerCase() === 'x-tokportal-dry-run')?.[1];\nif (!Number.isInteger(response.statusCode) || response.statusCode < 200 || response.statusCode >= 300 || marker !== 'true' || body?.dry_run !== true || body?.credits_charged !== 0) {\n  throw new Error('No verified preview. Stop and inspect the HTTP response; never retry without the dry-run header.');\n}\nif (typeof body.credits_would_charge !== 'number' || !Number.isFinite(body.credits_would_charge) || body.credits_would_charge < 0) {\n  throw new Error('The preview did not return a valid price. Stop; do not substitute a cached price.');\n}\nif (!/^00000000-0000-4000-8000-[0-9a-f]{12}$/i.test(body.data?.bundle_id || '')) {\n  throw new Error('Expected a synthetic bundle ID. Stop; do not use this ID in another workflow.');\n}\nreturn [{ json: {\n  result: 'Simulation complete. No order was placed.',\n  country: 'USA',\n  platform: 'tiktok',\n  bundle_type: 'account_only',\n  dry_run: true,\n  credits_charged: 0,\n  credits_would_charge: body.credits_would_charge,\n  cost_breakdown: body.cost_breakdown,\n  synthetic_bundle_id: body.data.bundle_id,\n  next_step: 'Review the quote and current terms. Place a separate order in the web app only if you decide to buy.',\n  web_order_url: 'https://app.tokportal.com/bundles/create?utm_source=developers_tokportal&utm_medium=docs&utm_campaign=growth_us_launch_202609&utm_content=n8n_preview_result'\n} }];"
      }
    }
  ],
  "connections": {
    "Run preview manually": {
      "main": [
        [
          {
            "node": "Read markets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read markets": {
      "main": [
        [
          {
            "node": "Confirm US availability",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Confirm US availability": {
      "main": [
        [
          {
            "node": "Read workspace costs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read workspace costs": {
      "main": [
        [
          {
            "node": "Simulate one account",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simulate one account": {
      "main": [
        [
          {
            "node": "Verify preview and show quote",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}
