{
  "id": "8a0bc635a357b54d",
  "name": "Pay for an x402 API from n8n through the Settled proxy",
  "nodes": [
    {
      "parameters": {
        "content": "## Pay for an x402 API from n8n through the Settled proxy\n\n### How it works\n\nn8n never holds the wallet key. The settled-x402 proxy, a small process on your machine, holds it and does the paying: this workflow posts the request it wants made to the proxy (`POST /pay`) with a token. The proxy reads the endpoint's x402 quote and checks it with Settled (is the payTo the one Settled sees, did a real purchase from this seller deliver, is the seller on hold), holds it to your limits (a cap per call, a daily budget, the hosts you allow), and only then signs and pays. It hands back the answer, the payment and Settled's verdict, and screens the answer for instructions aimed at an agent. Clean answers go one way; refusals and flagged answers go the other, with the reason. The example pays $0.002 for Settled's own signed check of an endpoint.\n\n### Setup steps\n\n- On the machine n8n runs on, make a wallet for the proxy: `mkdir -p ~/.settled-x402 && (umask 077; openssl rand -hex 32 > ~/.settled-x402/proxy-key)`\n- Start the proxy: `npx -y -p settled-x402 -p @x402/fetch@2 -p @x402/evm@2 -p viem@2 settled-x402 proxy --max-usd-per-call 0.25 --daily-budget-usd 5`. It prints the wallet's address and, the first time, a token (kept in `~/.settled-x402/proxy-token`).\n- Send that wallet a small float of USDC on Base, an amount you'd be fine losing. It is a wallet for this proxy only, never your main one; it needs no ETH.\n- In Pay Through Settled Proxy, create a Header Auth credential: Name `Authorization`, Value `Bearer <token>`.\n- In Request to Pay For, set the endpoint's `url`, its `method` and, for a POST, its `body`. n8n in Docker Desktop: set `proxy` to `http://host.docker.internal:4021`; with docker compose, run the proxy as a service on n8n's network and use `http://settled-proxy:4021` (the compose file: https://settled.tools/loadout, body n8n).\n\n### Customization\n\nPin the proxy to the hosts you mean to pay with `--only-hosts api.example.com` (anything else is refused before it is requested), stop more verdicts with `--block avoid,caution`, and refuse flagged answers outright with `--screen throw`. https://settled.tools/loadout builds the whole command from your limits and the services you pick. If n8n's SSRF protection is on, add the proxy's host to `N8N_SSRF_ALLOWED_HOSTNAMES`. What the proxy returns: https://settled.tools/for-agents#n8n-pay",
        "height": 980,
        "width": 480
      },
      "id": "8e0c2187-e826-51f1-9440-3a31bfc60c97",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -800,
        -32
      ]
    },
    {
      "parameters": {
        "content": "## Ask the proxy to pay, then sort the answer\n\nThe proxy checks the quote with Settled and your limits before it signs anything. The IF splits clean answers from refusals and answers the screen flagged.",
        "height": 420,
        "width": 1180,
        "color": 7
      },
      "id": "0a1f78aa-a1dd-565f-9ba9-8547c145d4a7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -240,
        -32
      ]
    },
    {
      "parameters": {},
      "id": "7a74a855-b31a-5fbb-b0c1-15ec6ac62127",
      "name": "Run It",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -200,
        100
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "3784506f-395a-5a88-95cb-8145e75a91a2",
              "name": "proxy",
              "value": "http://localhost:4021",
              "type": "string"
            },
            {
              "id": "e2ffdf50-fd24-5734-a10a-33882272f8ae",
              "name": "url",
              "value": "https://settled.tools/v1/check?url=https://x402.ottoai.services/whois-lookup",
              "type": "string"
            },
            {
              "id": "98698344-b40e-5d68-8145-4b248ed0106f",
              "name": "method",
              "value": "GET",
              "type": "string"
            },
            {
              "id": "099b5e4d-43fc-5e15-80bc-0f9e0c551ef4",
              "name": "body",
              "value": "={{ {} }}",
              "type": "object"
            }
          ]
        },
        "options": {}
      },
      "id": "25406de5-4f52-55f0-9c8c-fab681213dd6",
      "name": "Request to Pay For",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        40,
        100
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $json.proxy }}/pay",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ url: $json.url, method: $json.method, body: $json.body }) }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "e9279f40-e633-5f4f-adcd-e426dc1731d3",
      "name": "Pay Through Settled Proxy",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        280,
        100
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "aabf8286-c529-5e4c-9684-835901831bae",
              "leftValue": "={{ $json.ok }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            },
            {
              "id": "9cb0a531-7b47-5fd5-af0c-6e86dcfdfcdc",
              "leftValue": "={{ $json.screen ? $json.screen.verdict : 'none' }}",
              "rightValue": "suspicious",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "id": "a48b70db-5703-5c5a-b696-8ed5cf6e21c9",
      "name": "Answer Came Back Clean?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        520,
        100
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "b014a3d6-784a-5777-9152-fab2dc9cc9d4",
              "name": "answer",
              "value": "={{ $json.json !== undefined ? $json.json : { text: $json.body } }}",
              "type": "object"
            },
            {
              "id": "82c151e4-fd8c-50cc-9814-8265ce7d581e",
              "name": "paid",
              "value": "={{ $json.paid }}",
              "type": "boolean"
            },
            {
              "id": "346d93c4-e12a-58e4-a9ab-a6382a908ce0",
              "name": "price_usd",
              "value": "={{ $json.settled ? $json.settled.price_usd : 0 }}",
              "type": "number"
            },
            {
              "id": "6f881d63-5d27-558e-9551-6a72e2bfc0ce",
              "name": "tx",
              "value": "={{ $json.payment && $json.payment.tx ? $json.payment.tx : '' }}",
              "type": "string"
            },
            {
              "id": "5cd53ef7-1514-528d-9eed-0975459ad117",
              "name": "settled_verdict",
              "value": "={{ $json.settled ? $json.settled.verdict : 'no payment asked' }}",
              "type": "string"
            }
          ]
        },
        "options": {
          "ignoreConversionErrors": true
        }
      },
      "id": "baf4652a-1994-581f-904d-fb2f8d4f47c5",
      "name": "Answer",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        780,
        20
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "3749216d-85b8-5dd0-b7d3-d3800165c0b4",
              "name": "reason",
              "value": "={{ $json.blocked ? 'Refused (' + $json.blocked_by + '): ' + $json.message : ($json.screen && $json.screen.verdict === 'suspicious') ? 'Paid, but the answer carries instructions aimed at an agent (' + $json.screen.findings.map(f => f.kind).join(', ') + '). Read it yourself before any agent does.' : $json.error ? $json.error + ': ' + ($json.message || '') : 'The endpoint answered HTTP ' + $json.status }}",
              "type": "string"
            },
            {
              "id": "ee5975e8-6871-5deb-8ee9-2e120093a2f5",
              "name": "blocked_by",
              "value": "={{ $json.blocked_by || ($json.screen && $json.screen.verdict === 'suspicious' ? 'screen' : '') }}",
              "type": "string"
            },
            {
              "id": "3ab4174c-8d4c-5830-9902-adee37ec0213",
              "name": "paid",
              "value": "={{ !!$json.paid }}",
              "type": "boolean"
            },
            {
              "id": "cd6fbc91-6835-51cd-82d1-f676d8fbfff9",
              "name": "status",
              "value": "={{ $json.status || 0 }}",
              "type": "number"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "38732d82-14a1-5c18-802e-8e78d85a4063",
      "name": "Refused or Flagged",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        780,
        220
      ]
    }
  ],
  "connections": {
    "Run It": {
      "main": [
        [
          {
            "node": "Request to Pay For",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Request to Pay For": {
      "main": [
        [
          {
            "node": "Pay Through Settled Proxy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pay Through Settled Proxy": {
      "main": [
        [
          {
            "node": "Answer Came Back Clean?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Answer Came Back Clean?": {
      "main": [
        [
          {
            "node": "Answer",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Refused or Flagged",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false,
    "instanceId": "settled-tools-template"
  },
  "tags": []
}
