Skip to main content
This guide targets n8n users. It uses linkedin-search-people but you can apply the same patterns to other actions by changing the path and JSON body. Goals:
  • How To — Tips and good practice to implement Edges.
  • Fewer webhooks — use Edges callback.on: "final" for async so you get one callback per run, then pull data with GET /v1/runs/{run_uid}/outputs (Callbacks).
  • Fewer unnecessary API calls — paginate with X-Pagination-Next until done;

1. Set the request body to JSON

Use an HTTP Request node:
  1. Method POST.
  2. Enable Send Body.
  3. Body Content Type → JSON.
  4. Paste or build your JSON.
n8n Cloud HTTP Request node showing JSON body configuration for Edges API
You can also set the Accept: application/json header to ensure the response is in JSON format.

2. Send the X-API-Key header

For each request to the Edges API you need to authenticate thanks to your API key. Edges authenticates with X-API-Key (not Bearer). Add a header field
n8n Cloud HTTP Request headers with X-API-Key for Edges API
Consider creating a Custom Authentication using n8n’s Generic Credential Type. This allows you to securely store and reuse your credentials across all HTTP Request nodes in your workflows, improving both security and convenience.
n8n Cloud HTTP Request with Custom Auth for Edges API

3. Show headers and body

Enable Include Response Headers and Status / Full response (wording depends on n8n version). The item shape is typically like { body, headers, statusCode } so the next step can read headers['x-pagination-next'].
n8n Cloud HTTP Request showing headers, JSON body, and full response option for Edges

Live mode: native loop on X-Pagination-Next

In live mode, Edges returns the next page as a full URL in the X-Pagination-Next header. Call it exactly as returned. stop when the header is missing or empty.

Simple implementation

  1. Edit Field cursor to empty string or with the returned cursor header ← {{ $runIndex === 0 ? '' : $('Extract Pagination Cursor').first().json.pagination_cursor }}
  2. Check if cursor is set. If empty then launch the first request. If cursor exist then go to the cursor request.
  3. HTTP Request — POST to https://api.edges.run/v1/actions/linkedin-search-people/run/live and full response enabled. Or use the cursor as URL.
  4. Edit Field — extract cursor
  5. Check if cursor is returned. If cursor exist then go back to the first step of the loop !
  6. If no cursor is returned then continue. You have to process or store the results during the loop.
Add a max iteration safeguard (n8n workflow settings timeout, or a small counter — see optional Code) so a bug cannot run forever.
n8n Cloud workflow: Set, IF, and HTTP Request loop for Edges live pagination

Importable workflow (live loop)

Replace the placeholder key in both HTTP nodes after import. Complete the canvas so HTTP Next page connects back to Extract pagination.
Copy Paste this json directly into your n8n workflow editor Then edit the API keys and input request URL
{
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [-256, -272],
      "id": "ebf5bc97-b994-4c4f-9784-f04bca7f0bec",
      "name": "When clicking ‘Execute workflow’"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "1b593099-50d6-4fa7-85b3-bd41ccb0e989",
              "leftValue": "={{ $json.cursor }}",
              "rightValue": "''",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [224, -272],
      "id": "2dd0338d-de01-4847-9f31-6546b5899597",
      "name": "If"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.edges.run/v1/actions/salesnavigator-search-people/run/live",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "page_size",
              "value": "25"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-Key",
              "value": "xxxx-MY-EDGES-API-KEY-xxxx"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"input\": {\n    \"sales_navigator_profile_search_url\": \"https://www.linkedin.com/sales/search/people?[REDACTED_SAVED_SEARCH_OR_QUERY]\",\n    \"custom_data\": {}\n  },\n  \"parameters\": {\n    \"exclude_crm_contacts\": false,\n    \"exclude_viewed_leads\": false\n  },\n  \"identity_mode\": \"managed\"\n}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [512, -384],
      "id": "980d947a-c966-47ab-b4f6-fd9b0c5cfc3f",
      "name": "First Request"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $('Extract Pagination Cursor').first().json.pagination_cursor }}",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "page_size",
              "value": "25"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-Key",
              "value": "xxxx-MY-EDGES-API-KEY-xxxx"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"input\": {\n    \"sales_navigator_profile_search_url\": \"https://www.linkedin.com/sales/search/people?[REDACTED_SAVED_SEARCH_OR_QUERY]\",\n    \"custom_data\": {}\n  },\n  \"parameters\": {\n    \"exclude_crm_contacts\": false,\n    \"exclude_viewed_leads\": false\n  },\n  \"identity_mode\": \"managed\"\n}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [512, -208],
      "id": "d2afc651-7e49-4d1d-8e92-50c8ff498e93",
      "name": "Cursor Request"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "cursor",
              "value": "={{ $runIndex === 0 ? '' : $('Extract Pagination Cursor').first().json.pagination_cursor }}",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "3c05caa0-ea80-4a3b-b476-db7f29f2be90",
      "name": "Loop Start",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [16, -272]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "pagination_cursor",
              "value": "={{ $json.headers['x-pagination-next'] }}",
              "type": "string"
            },
            {
              "id": "id-2",
              "name": "results",
              "value": "={{ $json.body }}",
              "type": "array"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "f4528818-b1d3-46a9-a657-f5891e5b90ca",
      "name": "Extract Pagination Cursor",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [848, -272]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "id-1",
              "leftValue": "={{ $('Extract Pagination Cursor').first().json.pagination_cursor }}",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "2f279d41-385d-4f9b-a8e7-28f26b3d4e9f",
      "name": "More Pages?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [1072, -224]
    }
  ],
  "connections": {
    "When clicking ‘Execute workflow’": {
      "main": [[{ "node": "Loop Start", "type": "main", "index": 0 }]]
    },
    "If": {
      "main": [
        [{ "node": "First Request", "type": "main", "index": 0 }],
        [{ "node": "Cursor Request", "type": "main", "index": 0 }]
      ]
    },
    "First Request": {
      "main": [[{ "node": "Extract Pagination Cursor", "type": "main", "index": 0 }]]
    },
    "Cursor Request": {
      "main": [[{ "node": "Extract Pagination Cursor", "type": "main", "index": 0 }]]
    },
    "Loop Start": {
      "main": [[{ "node": "If", "type": "main", "index": 0 }]]
    },
    "Extract Pagination Cursor": {
      "main": [[{ "node": "More Pages?", "type": "main", "index": 0 }]]
    },
    "More Pages?": {
      "main": [
        [{ "node": "Loop Start", "type": "main", "index": 0 }],
        []
      ]
    }
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  }
}

Async mode: final webhook + outputs pagination

Why callback.on: "final"

With "final", Edges sends one callback when the run finishes instead of streaming many callbacks. That fits n8n Cloud well: one Webhook execution per run, then you pull the full result set with the outputs API (Streaming vs final callbacks).

Start the async run

HTTP Request POST on https://api.edges.run/v1/actions/linkedin-search-people/run/async Body example (replace the webhook URL with yours):
{
  "parameters": {},
  "identity_mode": "managed",
  "callback": {
    "url": "https://YOUR-SUBDOMAIN.app.n8n.cloud/webhook/edges-async-final",
    "on": "final"
  }
}

When the Webhook fires

The payload includes run.run_uid (see Callbacks). Use Edit Fields (Set):
  1. HTTP Request — method GET. In the URL field, use the runUid returned to the callback. https://api.edges.run/v1/runs/{{ $json.runUid }}/outputs and enable full response.
  2. Same Set / IF / HTTP pattern as live mode:
    • nextUrl from x-pagination-next
  3. Loop until no cursor are returned.