{
  "info": {
    "_postman_id": "28fafe68-c374-5a19-b5ac-6aeaf12bc634",
    "name": "Relay API — Manual testing",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "description": "Complete Relay customer HTTP API: 23 method/path pairs and all 22 LinkedIn capabilities, plus useful variants and a synthetic smoke. Import a supplied environment and fill your own credentials. Start with Health and List connections. Requests contain descriptions of inputs, limits, scopes and results. Send requests individually; this is not a whole-collection test run because it contains real sends and deletion. No scripts make network calls or automatically poll. Secrets are blank in distributed files. See postman/README.md and docs/linkedin-user-manual.md in the repository."
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Common authentication and JSON-safe environment substitution. No network calls.",
          "pm.request.headers.upsert({key: \"Accept\", value: \"application/json\"});",
          "pm.request.headers.upsert({key: \"User-Agent\", value: \"Relay-Postman/1.0\"});",
          "for (const [header, variable] of [",
          "    [\"CF-Access-Client-Id\", \"cf_access_client_id\"],",
          "    [\"CF-Access-Client-Secret\", \"cf_access_client_secret\"]",
          "]) {",
          "    const value = pm.environment.get(variable);",
          "    if (value) pm.request.headers.upsert({key: header, value});",
          "    else pm.request.headers.remove(header);",
          "}",
          "// Escape body variables in temporary local scope. The request body is immutable;",
          "// Postman performs its normal substitution after this script. No secrets persist",
          "// in the collection, and quotes/newlines remain valid JSON string contents.",
          "if (pm.request.body && pm.request.body.mode === \"raw\" && pm.request.body.raw) {",
          "    for (const match of pm.request.body.raw.matchAll(/{{([a-z_][a-z0-9_]*)}}/g)) {",
          "        const value = pm.environment.get(match[1]);",
          "        if (value !== undefined) {",
          "            pm.variables.set(match[1], JSON.stringify(String(value)).slice(1, -1));",
          "        }",
          "    }",
          "}",
          "// One stable key per request and run. Clicking Send again retries that operation.",
          "// Clear operation_run_id for a new intentional operation, including a fresh read.",
          "if (pm.request.headers.has(\"Idempotency-Key\")) {",
          "    let key = pm.environment.get(\"idempotency_key\");",
          "    if (!key) {",
          "        let run = pm.environment.get(\"operation_run_id\");",
          "        if (!run) {",
          "            run = pm.variables.replaceIn(\"{{$guid}}\");",
          "            pm.environment.set(\"operation_run_id\", run);",
          "        }",
          "        key = \"relay-\" + run + \"-\" + pm.info.requestId;",
          "    }",
          "    pm.variables.set(\"request_idempotency_key\", key);",
          "    pm.environment.set(\"last_idempotency_key\", key);",
          "}"
        ]
      }
    }
  ],
  "item": [
    {
      "name": "00 Service",
      "description": "Check API/database reachability before testing LinkedIn. Hosted health still needs Cloudflare Access headers.",
      "item": [
        {
          "id": "f19dbcb2-c59c-5a70-a9c7-822751022108",
          "name": "Health",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/healthz",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "healthz"
              ]
            },
            "description": "Returns `{\"status\":\"ok\"}` when the API can query PostgreSQL. Does not prove LinkedIn login, proxy, browser worker, listener, or callbacks.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "01 Connections",
      "description": "Create a LinkedIn connection or choose an existing one. Copy a selected list result ID into connection_id; lists never auto-select an account.",
      "item": [
        {
          "id": "f7fcd27c-541b-5543-80a2-0de814e3f8ba",
          "name": "List connections",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/connections",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections"
              ]
            },
            "description": "Scope: `connections:read`. Returns `connections` without pagination. Select the intended account and copy its ID to `connection_id`. Check `regional_proxy_configured`; Relay supplies the proxy."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "9aa3c55d-e899-5c14-95f5-80028ce00b14",
          "name": "Get connection and capabilities",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}"
              ]
            },
            "description": "Scope: `connections:read`. Includes health, supported capabilities, region, proxy configuration and separate Recruiter health. Saves connection ID and authenticated actor ID, never a recipient."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const connection = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && connection.id && connection.provider) {",
                  "    pm.environment.set(\"connection_id\", connection.id);",
                  "    pm.environment.set(\"connection_health\", connection.health);",
                  "    if (connection.external_actor && connection.external_actor.id) {",
                  "        pm.environment.set(\"actor_id\", connection.external_actor.id);",
                  "    } else {",
                  "        pm.environment.unset(\"actor_id\");",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "2b65a86e-ee7c-55db-96f6-5bc9aeb0f8f4",
          "name": "Create LinkedIn connection",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections"
              ]
            },
            "description": "Scope: `connections:write`. Set `linkedin_username`, `linkedin_password`, and `region`. Two-letter region; password 1–1024 characters. Saves the new `connection_id`. Duplicate username in the workspace returns 409; use List connections to select the existing ID. Then submit Login.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"provider\": \"linkedin\",\n  \"username\": \"{{linkedin_username}}\",\n  \"password\": \"{{linkedin_password}}\",\n  \"region\": \"{{region}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([201]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const connection = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && connection.id && connection.provider) {",
                  "    pm.environment.set(\"connection_id\", connection.id);",
                  "    pm.environment.set(\"connection_health\", connection.health);",
                  "    if (connection.external_actor && connection.external_actor.id) {",
                  "        pm.environment.set(\"actor_id\", connection.external_actor.id);",
                  "    } else {",
                  "        pm.environment.unset(\"actor_id\");",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "02 Login and identity",
      "description": "Login can wait for an account-owner challenge. Reconnect refreshes a ready session and invalidates Recruiter readiness.",
      "item": [
        {
          "id": "7e2d1435-caa3-5ed9-b384-baeb68faec12",
          "name": "Login",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.login`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{}` or `{\"reconnect\":true}`\n\n**Result and limits:** `reason: \"login_succeeded\"` and `state_revision`; connection health becomes `ready`. A browser session and regional proxy are required.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.login\",\n  \"input\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "22838ad5-4ac7-5072-bec4-847dbfcdd0e8",
          "name": "Reconnect a ready account",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.login`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{}` or `{\"reconnect\":true}`\n\n**Result and limits:** `reason: \"login_succeeded\"` and `state_revision`; connection health becomes `ready`. A browser session and regional proxy are required.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.login\",\n  \"input\": {\n    \"reconnect\": true\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "b757bc02-30f9-5b17-ab2e-2b81b6807ee1",
          "name": "Check saved LinkedIn session",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.health.check`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{}`\n\n**Result and limits:** Opens the saved browser session through its pinned proxy, checks the feed and authenticated identity, and returns `health: \"ready\"`, `actor_id`, and `state_revision` on success. Requires an existing ready session. An authentication or identity failure updates connection health; other errors appear as operation failures. This is an explicit provider check, unlike `/healthz`.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.health.check\",\n  \"input\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "30c04ec3-4d61-54c2-b902-dad54a01e1a2",
          "name": "Get authenticated identity",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.identity.get`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{}`\n\n**Result and limits:** `actor_id`, `hash_id`, `public_id`, `member_id`, `firstName`, `lastname`, `headline`, `avatar` when supplied, plus `state_revision`. Use `actor_id` to identify the authenticated account.\n\nThe result actor_id identifies your own LinkedIn account. It is not the target person. The poll request saves it to actor_id.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.identity.get\",\n  \"input\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "03 Operations",
      "description": "All LinkedIn capabilities are asynchronous. These controls use the last saved operation_id. Nothing polls automatically.",
      "item": [
        {
          "id": "a31aec55-8a5c-539a-931a-d78b98d1528a",
          "name": "Get operation",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/operations/{{operation_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "operations",
                "{{operation_id}}"
              ]
            },
            "description": "Scope: `operations:read`. Poll manually. Statuses: queued, running, waiting_user, succeeded, failed, skipped, canceled, outcome_unknown. Saves status, challenge ID, own actor ID, and available next-page metadata. No automatic recipient selection or write retry."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "fc81120e-afc2-516c-acf7-ebadfb4c9d35",
          "name": "Submit current 2FA code",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/operations/{{operation_id}}/challenge",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "operations",
                "{{operation_id}}",
                "challenge"
              ]
            },
            "description": "Scope: `operations:write`. Only a current waiting email/sms/authenticator challenge accepts a code (1–32 printable characters). Poll first to save challenge_id; fill challenge_code locally. LinkedIn app confirmation/account-owner actions happen in LinkedIn, not this request.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"challenge_id\": \"{{challenge_id}}\",\n  \"code\": \"{{challenge_code}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([202]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "d0dd25ea-4e31-57c2-9926-79addc897c2f",
          "name": "Cancel operation",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/operations/{{operation_id}}/cancel",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "operations",
                "{{operation_id}}",
                "cancel"
              ]
            },
            "description": "Scope: `operations:write`. Queued work cancels immediately; running work receives a cancellation request. It cannot undo an external action already performed."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "84cfced5-5cf7-5c7a-b3ff-fb5c11ca16f4",
          "name": "Reconcile unknown outcome",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/operations/{{operation_id}}/reconcile",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "operations",
                "{{operation_id}}",
                "reconcile"
              ]
            },
            "description": "Scope: `operations:write`. Only outcome_unknown is eligible; otherwise 409. LinkedIn currently has no evidence reconciler, so its unknown result stays unknown. Inspect the relevant read API before any new send."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "04 Profiles and network",
      "description": "Read profiles, actor IDs, connections, companies, and pending outgoing invitations.",
      "item": [
        {
          "id": "d3a301d8-f177-5d04-abbf-60306a827b99",
          "name": "Get profile by public slug",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.profile.get`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"profile_id\":\"jane-example\"}`\n\n**Result and limits:** `profile` with selected basic/contact profile fields, plus `state_revision`. Public slug: 1–255 letters, digits, `_`, `.`, or `-`.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.profile.get\",\n  \"input\": {\n    \"profile_id\": \"{{profile_id}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "cf9ff901-e1ef-591e-85e6-a3e160928c07",
          "name": "Resolve public slugs to actor IDs",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.hash_ids.resolve`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"public_ids\":[\"jane-example\"]}`\n\n**Result and limits:** `hash_ids` mapping the supplied public IDs to actor hash IDs, plus `state_revision`. Supply 1–25 public IDs. Useful before sending to a profile found by public slug.\n\nInspect result.hash_ids and manually copy the intended target to recipient_actor_id. Add up to 25 slugs to public_ids.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.hash_ids.resolve\",\n  \"input\": {\n    \"public_ids\": [\n      \"{{profile_id}}\"\n    ]\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "c89e01e4-5d87-565a-b311-b653c67d9745",
          "name": "List connections",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.connections.list`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"count\":25,\"start\":0}`\n\n**Result and limits:** `connections` array; entries include `hash_id`, `public_id`, names, headline, avatar, and `connected_at` when supplied. `count` 1–50, `start` 0–10000; defaults 25 and 0. Increase `start` for the next page.\n\nEdit start for the next page and clear operation_run_id before sending the changed input.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.connections.list\",\n  \"input\": {\n    \"start\": 0,\n    \"count\": 25\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "43936ddf-9431-5fc0-b3a6-9a43ff7b7f8f",
          "name": "Get company by public slug",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.company.get`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** Exactly one of `{\"public_id\":\"example-co\"}`, `{\"company_id\":\"12345\"}`, or `{\"company_name\":\"Example Co\"}`\n\n**Result and limits:** `company` object with mapped company details. Numeric `company_id` is a string of at most 20 digits.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.company.get\",\n  \"input\": {\n    \"public_id\": \"{{company_public_id}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "6f854026-74f4-5cfa-9619-f935649b784e",
          "name": "Get company by numeric ID",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.company.get`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** Exactly one of `{\"public_id\":\"example-co\"}`, `{\"company_id\":\"12345\"}`, or `{\"company_name\":\"Example Co\"}`\n\n**Result and limits:** `company` object with mapped company details. Numeric `company_id` is a string of at most 20 digits.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.company.get\",\n  \"input\": {\n    \"company_id\": \"{{company_id}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "df385710-9446-5ae4-bcc1-990b0799d6e3",
          "name": "Get company by name",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.company.get`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** Exactly one of `{\"public_id\":\"example-co\"}`, `{\"company_id\":\"12345\"}`, or `{\"company_name\":\"Example Co\"}`\n\n**Result and limits:** `company` object with mapped company details. Numeric `company_id` is a string of at most 20 digits.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.company.get\",\n  \"input\": {\n    \"company_name\": \"{{company_name}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "74df7cd4-a15e-509b-8281-a9487543b8c6",
          "name": "List sent pending invitations",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.invitations.sent.list`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"start_index\":0,\"include_total\":true}`\n\n**Result and limits:** Returns pending outgoing invitations: `entries`, `count`, `start_index`, `has_more`, `next_start_index`, optional `total`. Pages contain up to ten items. Follow `next_start_index` until `has_more` is false; a short nonempty page still requires another read. Dedupe by `invitation_id` because invitations may be accepted or withdrawn while paging. `start_index` must be a multiple of ten from 0 to 100000. `include_total` defaults to false; when requested, `total` is LinkedIn's advisory count or null if unavailable. Provider errors return a failed operation with `upstream_error` and safe `upstream_status`; an unfamiliar page or response returns `parsing_error`, never a successful empty inventory.\n\nFollow result.next_start_index while result.has_more. The poll helper stores next_sent_invitation_start for reference; set the body start_index to that integer and clear operation_run_id. Accepted connections are not pending invitations.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.invitations.sent.list\",\n  \"input\": {\n    \"start_index\": 0,\n    \"include_total\": true\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "05 Search",
      "description": "Search results do not automatically become send targets. Inspect the person and set recipient_actor_id yourself.",
      "item": [
        {
          "id": "0aa9962e-0261-5bb8-b95d-522a0def7664",
          "name": "Standard typeahead",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.typeahead`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"kind\":\"company\",\"keyword\":\"Example\"}`\n\n**Result and limits:** `kind`, `items`, `state_revision`. Kinds: `company`, `job_function`, `industry`, `location`, `people`, `school`, `skill`, `job_title`. Keyword: 1–100 printable characters. Use returned IDs when a search filter needs one.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.typeahead\",\n  \"input\": {\n    \"kind\": \"company\",\n    \"keyword\": \"{{company_name}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "27b2541f-4271-5205-8923-20d2080a3c18",
          "name": "Search people",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.people.search`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"keywords\":\"engineer\",\"filters\":{\"location_name\":\"New York\"},\"start\":0,\"count\":25}`\n\n**Result and limits:** `people` list and `start`, plus `state_revision`. At least one keyword or filter is required. `start` 0–1000. `count` 1–50 caps returned rows; the upstream people handler controls its own page size, so a page may contain fewer than `count`. Advance `start` by the number of returned rows.\n\n**All supported people filters:**  `filters` accepts exactly these keys (strings up to 100 printable characters unless stated otherwise): `location_id`, `current_company_id`, `past_company_id`, `industry_id`, `network`, `connection_of`, `follower_of`, `profile_language`, `school_id`, `service_category_id`, `first_name`, `last_name`, `title`, `company`, `school`, `location_name`, `current_company_name`, `past_company_name`, `industry_name`, `connection_of_name`, `follower_of_name`, `school_name`, `service_category_name`, and boolean `open_to_volunteer`. The `*_name` filters are resolved through server-side typeahead; resolve ambiguity by using an ID when available. `keywords` is up to 200 printable characters.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.people.search\",\n  \"input\": {\n    \"keywords\": \"{{people_keywords}}\",\n    \"filters\": {},\n    \"start\": 0,\n    \"count\": 25\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "ba238de8-a742-5db0-8df3-68f47e8bc38b",
          "name": "Search people at a company",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.people.search`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"keywords\":\"engineer\",\"filters\":{\"location_name\":\"New York\"},\"start\":0,\"count\":25}`\n\n**Result and limits:** `people` list and `start`, plus `state_revision`. At least one keyword or filter is required. `start` 0–1000. `count` 1–50 caps returned rows; the upstream people handler controls its own page size, so a page may contain fewer than `count`. Advance `start` by the number of returned rows.\n\n**All supported people filters:**  `filters` accepts exactly these keys (strings up to 100 printable characters unless stated otherwise): `location_id`, `current_company_id`, `past_company_id`, `industry_id`, `network`, `connection_of`, `follower_of`, `profile_language`, `school_id`, `service_category_id`, `first_name`, `last_name`, `title`, `company`, `school`, `location_name`, `current_company_name`, `past_company_name`, `industry_name`, `connection_of_name`, `follower_of_name`, `school_name`, `service_category_name`, and boolean `open_to_volunteer`. The `*_name` filters are resolved through server-side typeahead; resolve ambiguity by using an ID when available. `keywords` is up to 200 printable characters.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.people.search\",\n  \"input\": {\n    \"keywords\": \"{{people_keywords}}\",\n    \"filters\": {\n      \"current_company_name\": \"{{company_name}}\"\n    },\n    \"start\": 0,\n    \"count\": 25\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "7852816c-e40e-5232-9fa4-7517989ec46d",
          "name": "Search jobs",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.jobs.search`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"keywords\":\"engineer\",\"filters\":{\"company_name\":\"Example\"},\"start\":0,\"count\":25}`\n\n**Result and limits:** `jobs` list and `start`, plus `state_revision`. At least one keyword or filter is required. `start` 0–1000, `count` 1–50. Optional `decoration_id` (up to 255 characters) and `job_details_count`, `job_posting_detail_description_start`, `job_posting_detail_description_count` (each integer 0–1000) control LinkedIn job-detail retrieval.\n\n**All supported job filters:**  `filters` accepts: `location_id`, `company_id`, `time_posted_range`, `job_type`, `sort_by`, `commitment`, `distance`, `experience_level`, `function_id`, `industry_id`, `populated_place_geo_id`, `salary_bucket`, `title_id`, `workplace_type`, `location_name`, `company_name`, `function_name`, `industry_name`, `populated_place_name`, `title_name` (strings up to 100 printable characters), and `apply_with_linkedin`, `early_applicant`, `in_your_network` (booleans). The `*_name` forms request server-side resolution. LinkedIn determines the meaning of upstream value strings; typeahead and live results are the safest way to select them.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.jobs.search\",\n  \"input\": {\n    \"keywords\": \"{{job_keywords}}\",\n    \"filters\": {},\n    \"start\": 0,\n    \"count\": 25\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "06 Conversations and messages",
      "description": "Read conversations before sending. recipient_actor_id is a LinkedIn profile hash ID; conversation_id is returned by conversation APIs.",
      "item": [
        {
          "id": "2b149fe8-e94b-5932-9ee6-12dcc01585a5",
          "name": "List conversations",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.conversations.list`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{}` or `{\"category\":\"PRIMARY_INBOX\",\"count\":20,\"cursor\":\"<next-cursor>\"}`\n\n**Result and limits:** `conversations`, `next_cursor`, `state_revision`. Categories: `PRIMARY_INBOX` (default), `SECONDARY_INBOX`, `INMAIL`, `ARCHIVE`, `SPAM`; count 1–20. Pass the returned cursor for the next page. Alternatively pass `last_activity_at` as a decimal millisecond timestamp, which is Prox's older coarse cursor; use one cursor form at a time. Conversation entries include `conversation_id`, participant hash IDs, unread count, and activity time when supplied.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.conversations.list\",\n  \"input\": {\n    \"category\": \"PRIMARY_INBOX\",\n    \"count\": 20\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "5d2c5198-e2d6-5c44-83a4-f20e858eee05",
          "name": "List next conversation page",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.conversations.list`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{}` or `{\"category\":\"PRIMARY_INBOX\",\"count\":20,\"cursor\":\"<next-cursor>\"}`\n\n**Result and limits:** `conversations`, `next_cursor`, `state_revision`. Categories: `PRIMARY_INBOX` (default), `SECONDARY_INBOX`, `INMAIL`, `ARCHIVE`, `SPAM`; count 1–20. Pass the returned cursor for the next page. Alternatively pass `last_activity_at` as a decimal millisecond timestamp, which is Prox's older coarse cursor; use one cursor form at a time. Conversation entries include `conversation_id`, participant hash IDs, unread count, and activity time when supplied.\n\nUse only when a previous successful result returned a nonempty next_cursor. Clear operation_run_id each time this request is used for another page.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.conversations.list\",\n  \"input\": {\n    \"category\": \"PRIMARY_INBOX\",\n    \"count\": 20,\n    \"cursor\": \"{{next_conversation_cursor}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "2cc0ef3b-0723-5345-9478-5ee7495be995",
          "name": "Search conversations",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.conversations.search`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"keywords\":\"Example\",\"categories\":[\"INBOX\"],\"count\":20}`\n\n**Result and limits:** `conversations`, `next_cursor`, `state_revision`. Keyword 1–100 characters; categories from `INBOX`, `SPAM`, `ARCHIVE`, `INMAIL` (default: `INBOX`, `SPAM`, `ARCHIVE`); optional `first_degree_connections` boolean and `cursor`; count 1–20.\n\nOptional cursor can be added from result.next_cursor. Search categories differ from list categories.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.conversations.search\",\n  \"input\": {\n    \"keywords\": \"{{conversation_keywords}}\",\n    \"categories\": [\n      \"INBOX\",\n      \"SPAM\",\n      \"ARCHIVE\"\n    ],\n    \"first_degree_connections\": false,\n    \"count\": 20\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "8040a72b-24a5-5fd6-ba75-ae51a792e3b6",
          "name": "Find conversation with recipient",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.conversation.with_recipient`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"recipient_actor_id\":\"<actor-hash-id>\"}`\n\n**Result and limits:** `conversation` object if a conversation exists, plus `state_revision`. Useful to find a thread before sending.\n\nInspect result.conversation and copy its conversation_id to the environment. This does not send a message or create a conversation.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.conversation.with_recipient\",\n  \"input\": {\n    \"recipient_actor_id\": \"{{recipient_actor_id}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "df055359-3e91-5008-a0af-682df96f3417",
          "name": "List messages",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.messages.list`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"conversation_id\":\"<conversation-id>\",\"count\":20}`\n\n**Result and limits:** `messages` array and `state_revision`; count 1–20 is sent upstream. Optional `cursor` maps to Prox's `prev_cursor`. Alternatively use `delivered_at` from the oldest returned message as a decimal millisecond timestamp to request earlier messages; dedupe by `message_urn` because boundary rows can repeat. Use one cursor form at a time. A `conversation_urn` may replace `conversation_id` or accompany its matching ID; it must name the authenticated actor. The upstream handler does not expose a next cursor. Message entries can include `message_urn`, `message_body`, `sender_hash_id`, `delivered_at`, and attachment render content. Treat content as customer data.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.messages.list\",\n  \"input\": {\n    \"conversation_id\": \"{{conversation_id}}\",\n    \"count\": 20\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "03081f7e-5235-5ea5-a0f7-aa8f05a25e6c",
          "name": "List older messages by timestamp",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.messages.list`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"conversation_id\":\"<conversation-id>\",\"count\":20}`\n\n**Result and limits:** `messages` array and `state_revision`; count 1–20 is sent upstream. Optional `cursor` maps to Prox's `prev_cursor`. Alternatively use `delivered_at` from the oldest returned message as a decimal millisecond timestamp to request earlier messages; dedupe by `message_urn` because boundary rows can repeat. Use one cursor form at a time. A `conversation_urn` may replace `conversation_id` or accompany its matching ID; it must name the authenticated actor. The upstream handler does not expose a next cursor. Message entries can include `message_urn`, `message_body`, `sender_hash_id`, `delivered_at`, and attachment render content. Treat content as customer data.\n\nSet oldest_message_delivered_at from the oldest returned row; dedupe message_urn at page boundaries. The service does not return a next message cursor.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.messages.list\",\n  \"input\": {\n    \"conversation_id\": \"{{conversation_id}}\",\n    \"count\": 20,\n    \"delivered_at\": \"{{oldest_message_delivered_at}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "6c9a6e94-5fa0-5293-ac68-2d3cb322b686",
          "name": "List messages by conversation URN",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.messages.list`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"conversation_id\":\"<conversation-id>\",\"count\":20}`\n\n**Result and limits:** `messages` array and `state_revision`; count 1–20 is sent upstream. Optional `cursor` maps to Prox's `prev_cursor`. Alternatively use `delivered_at` from the oldest returned message as a decimal millisecond timestamp to request earlier messages; dedupe by `message_urn` because boundary rows can repeat. Use one cursor form at a time. A `conversation_urn` may replace `conversation_id` or accompany its matching ID; it must name the authenticated actor. The upstream handler does not expose a next cursor. Message entries can include `message_urn`, `message_body`, `sender_hash_id`, `delivered_at`, and attachment render content. Treat content as customer data.\n\nactor_id must name the authenticated account, not the recipient. Fill it from identity or connection inspection.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.messages.list\",\n  \"input\": {\n    \"conversation_urn\": \"urn:li:msg_conversation:(urn:li:fsd_profile:{{actor_id}},{{conversation_id}})\",\n    \"count\": 20\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "07 Sends and files",
      "description": "Invitation, message, and attachment requests perform real LinkedIn actions when you click Send. Check destination and body first. Sends also require linkedin:send. Do not run this folder as a batch.",
      "item": [
        {
          "id": "325249b5-5bd3-51c4-81ff-efef19b382e5",
          "name": "Send invitation without a note",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.invitation.send`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll, and `linkedin:send`.\n\n**Input contract:** `{\"recipient_actor_id\":\"<actor-hash-id>\"}` with optional `\"message\":\"Short note\"`\n\n**Result and limits:** Invitation result includes `recipient_actor_id`, `code`, `message`, `provider_acknowledged: true`, and `state_revision`. Optional note 1–300 characters. Check `code` rather than assuming every acknowledgement means `SENT`.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.invitation.send\",\n  \"input\": {\n    \"recipient_actor_id\": \"{{recipient_actor_id}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "520b5fc8-d313-5054-84a6-6e077d74df61",
          "name": "Send invitation with a note",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.invitation.send`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll, and `linkedin:send`.\n\n**Input contract:** `{\"recipient_actor_id\":\"<actor-hash-id>\"}` with optional `\"message\":\"Short note\"`\n\n**Result and limits:** Invitation result includes `recipient_actor_id`, `code`, `message`, `provider_acknowledged: true`, and `state_revision`. Optional note 1–300 characters. Check `code` rather than assuming every acknowledgement means `SENT`.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.invitation.send\",\n  \"input\": {\n    \"recipient_actor_id\": \"{{recipient_actor_id}}\",\n    \"message\": \"{{invitation_note}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "9825afa2-9db6-5368-a559-640906f8fa23",
          "name": "Send message to a recipient",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.message.send`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll, and `linkedin:send`.\n\n**Input contract:** `{\"conversation_id\":\"<conversation-id>\",\"body\":\"Hello\"}` **or** `{\"recipient_actor_id\":\"<actor-hash-id>\",\"body\":\"Hello\"}`\n\n**Result and limits:** Exactly one destination. Body up to 2000 characters; either nonblank text or `render_content_unions` is required. Advanced Prox-style render content accepts up to five nonempty JSON objects totaling 16 KB, for example an already uploaded file union. Use `linkedin.attachment.send` for normal file uploads. Message text and render content are encrypted in durable input storage. Result contains `provider_acknowledged: true`, destination, `message_id` when LinkedIn supplies it, provider result fields, and `state_revision`.\n\nOptional render_content_unions supports up to 5 nonempty JSON objects (total 16384 UTF-8 bytes). The body may be empty only when render content is supplied.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.message.send\",\n  \"input\": {\n    \"recipient_actor_id\": \"{{recipient_actor_id}}\",\n    \"body\": \"{{message_body}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "2f9a5419-e64e-552a-88ac-a5502bb6bac5",
          "name": "Send message to a conversation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.message.send`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll, and `linkedin:send`.\n\n**Input contract:** `{\"conversation_id\":\"<conversation-id>\",\"body\":\"Hello\"}` **or** `{\"recipient_actor_id\":\"<actor-hash-id>\",\"body\":\"Hello\"}`\n\n**Result and limits:** Exactly one destination. Body up to 2000 characters; either nonblank text or `render_content_unions` is required. Advanced Prox-style render content accepts up to five nonempty JSON objects totaling 16 KB, for example an already uploaded file union. Use `linkedin.attachment.send` for normal file uploads. Message text and render content are encrypted in durable input storage. Result contains `provider_acknowledged: true`, destination, `message_id` when LinkedIn supplies it, provider result fields, and `state_revision`.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.message.send\",\n  \"input\": {\n    \"conversation_id\": \"{{conversation_id}}\",\n    \"body\": \"{{message_body}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "f7d71feb-514b-5bd4-9bd5-2de5d8cad15e",
          "name": "Send attachment to a conversation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.attachment.send`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll, and `linkedin:send`.\n\n**Input contract:** `{\"conversation_id\":\"<conversation-id>\",\"filename\":\"note.pdf\",\"content_type\":\"application/pdf\",\"data_base64\":\"<base64>\"}`; may use `recipient_actor_id` instead and optional `body`\n\n**Result and limits:** Exactly one destination. File must be 1–1,000,000 decoded bytes; filename 1–255 plain characters without slashes; valid media type; optional body up to 2000 characters. Result has send acknowledgement and message ID when supplied. Base64 encode the file bytes before JSON submission.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.attachment.send\",\n  \"input\": {\n    \"conversation_id\": \"{{conversation_id}}\",\n    \"filename\": \"{{attachment_filename}}\",\n    \"content_type\": \"{{attachment_content_type}}\",\n    \"data_base64\": \"{{attachment_base64}}\",\n    \"body\": \"{{message_body}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "15053c59-a63e-5762-97a6-9e5c41dd74a7",
          "name": "Send attachment to a recipient",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.attachment.send`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll, and `linkedin:send`.\n\n**Input contract:** `{\"conversation_id\":\"<conversation-id>\",\"filename\":\"note.pdf\",\"content_type\":\"application/pdf\",\"data_base64\":\"<base64>\"}`; may use `recipient_actor_id` instead and optional `body`\n\n**Result and limits:** Exactly one destination. File must be 1–1,000,000 decoded bytes; filename 1–255 plain characters without slashes; valid media type; optional body up to 2000 characters. Result has send acknowledgement and message ID when supplied. Base64 encode the file bytes before JSON submission.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.attachment.send\",\n  \"input\": {\n    \"recipient_actor_id\": \"{{recipient_actor_id}}\",\n    \"filename\": \"{{attachment_filename}}\",\n    \"content_type\": \"{{attachment_content_type}}\",\n    \"data_base64\": \"{{attachment_base64}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "f8897b28-21c4-5be0-b4fe-1856dd9e4140",
          "name": "Download LinkedIn file as base64",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.file.download`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"url\":\"https://media.licdn.com/...\"}`\n\n**Result and limits:** `content_type`, `data_base64`, `size`, `state_revision`. URL must be HTTPS on `linkedin.com`/`licdn.com` or a subdomain, with no credentials and no nonstandard port. The current service does not enforce a download-size cap; apply your own response-size limit and decode base64 on your side.\n\nA read operation. Copy a real LinkedIn attachment URL into file_url; the placeholder is not a working file. Decode result.data_base64 outside Postman if needed.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.file.download\",\n  \"input\": {\n    \"url\": \"{{file_url}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "08 Recruiter",
      "description": "Requires an account with Recruiter entitlement and a successful verified switch. Switching changes saved session state; it can require account-owner action.",
      "item": [
        {
          "id": "4e688acd-b578-579c-bfb8-4a6c1ef0cca4",
          "name": "Switch to Recruiter contract",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.recruiter.switch`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{}` or `{\"contract\":\"Recruiter\"}`; contract text up to 100 characters\n\n**Result and limits:** Switches the account's matching Recruiter contract and verifies a read-only Recruiter search before publishing the session. Requires ordinary connection health `ready`. The connection's separate `recruiter.health` must become `ready` before Recruiter reads.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.recruiter.switch\",\n  \"input\": {\n    \"contract\": \"{{recruiter_contract}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "70944fd0-aebc-556c-a803-9e5e8a83f835",
          "name": "Recruiter typeahead",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.recruiter.typeahead`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"kind\":\"job_title\",\"keyword\":\"Engineer\"}`\n\n**Result and limits:** `kind`, `items`, `state_revision`. Kinds: `company`, `industry`, `job_title`, `location`, `school`, `skill`, `zip`. Requires `recruiter.health: \"ready\"`.\n\n\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.recruiter.typeahead\",\n  \"input\": {\n    \"kind\": \"job_title\",\n    \"keyword\": \"{{recruiter_title}}\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "5ead94c3-900e-5865-adfb-a8933c7cb99d",
          "name": "Search Recruiter people",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `linkedin.recruiter.people.search`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\n**Input contract:** `{\"keywords\":\"engineer\",\"titles\":[\"Engineer\"],\"start\":0,\"count\":25}` or `{\"titles\":[{\"name\":\"Engineer\",\"title_id\":\"42\"}]}`\n\n**Result and limits:** `candidates`, `paging`, `total`, `formatted_total`, `facets`, `query_summary`, `highlight_terms`, and `state_revision`. Supplied title IDs are used directly; name-only titles are resolved by typeahead. Requires verified Recruiter readiness. `start` 0–1000, `count` 1–50; at least one keyword, title, or other filter is required. See Recruiter filters below.\n\n`titles` accepts up to ten strings or objects such as `{\"name\":\"Engineer\",\"filter_type\":\"must_have\",\"time_scope\":\"current\"}`. An optional `title_id` may be supplied in a title object. Supplied IDs are used directly; name-only entries are resolved through Recruiter typeahead. `filter_type` is `can_have` (default), `must_have`, or `doesnt_have`; title/company `time_scope` is `current_or_past` (default), `current`, `past`, or `past_not_current`. The accepted additional top-level fields are:\n\n| Field | Format |\n| --- | --- |\n| `first_names`, `last_names` | Lists of name strings. |\n| `locations` | List of location strings or `{name,filter_type?,geo_scope?}` objects. `geo_scope`: `current` (default), `preferred_not_current`, `current_or_preferred`. |\n| `skills`, `companies`, `schools`, `industries`, `current_companies`, `past_companies` | Lists of strings or `{name,filter_type?}` objects. `companies` may also use `time_scope`. Names are resolved through the relevant Recruiter typeahead. |\n| `zip_codes` | List of nonempty ZIP/postal-code strings. |\n| `company_sizes` | Letter codes `A`–`I`: self-employed, 1–10, 11–50, 51–200, 201–500, 501–1000, 1001–5000, 5001–10000, 10000+. |\n| `job_functions`, `seniorities` | Lists of numeric LinkedIn taxonomy codes. `job_functions` includes `8` for Engineering; `seniorities` uses 1–10 (for example 4 Senior, 5 Manager, 6 Director). Query Recruiter facets/results to choose other codes. |\n| `networks` | Codes `F` first-degree, `S` second-degree, `A` group members, `O` third-degree/others. |\n| `profile_languages` | Language codes such as `en`, `es`, `zh`, `de`, `fr`, `it`, `pt`, `nl`, `in`, `ms`, `ro`, `ru`; accepted codes are service-defined, so test uncommon codes before use. |\n| `recently_joined` | Integer buckets 1 (one day), 2 (2–7 days), 3 (8–14 days), 4 (15–30 days), 5 (1–3 months). |\n| `graduation_years`, `yoe` | Objects with integer `min` and/or `max`; `yoe` means years of experience. |\n| `is_veteran` | Boolean. |\n| `distance` | Positive integer, used with geographic criteria. |\n\nThe service validates many Recruiter filter details inside the copied handler, after accepting the operation. Invalid combinations may therefore produce a `failed` operation with `error_code: \"validation_error\"`. Start with keywords or a small set of filters, inspect results and `error_code`, then add filters. A valid empty search result still counts as a working Recruiter session. Recruiter candidate enrichment may leave `hash_id` absent; do not assume every candidate can immediately be messaged.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"linkedin.recruiter.people.search\",\n  \"input\": {\n    \"keywords\": \"{{job_keywords}}\",\n    \"titles\": [\n      \"{{recruiter_title}}\"\n    ],\n    \"start\": 0,\n    \"count\": 25\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "09 Subscriptions and listener",
      "description": "Active subscriptions cause real event ingestion and callback delivery. Set a receiver you control. All endpoints require events:read or events:write as stated.",
      "item": [
        {
          "id": "37cd8a92-d04d-5079-886b-8f2f0fa82f50",
          "name": "List subscriptions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/subscriptions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "subscriptions"
              ]
            },
            "description": "Scope: `events:read`. Returns subscriptions; manually copy the intended subscription ID. No list auto-selection."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "8d24afb1-4424-5e7e-95a4-cc5d99eb1701",
          "name": "Create subscription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/subscriptions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "subscriptions"
              ]
            },
            "description": "Scope: `events:write`. Set callback_url to your public HTTPS receiver (no query/fragment). Starts an active subscription. Types: message_received, message_sent, sponsored_inmail_received, custom_connection_request_accepted, connection.stream_degraded, connection.stream_restored. Connection confirmations are listener health signals. Optional secret: 32–255 characters; omitted here so the service generates one. Copy the once-only secret from the response into your receiver secret store; this collection intentionally does not save it into the environment. A repeated create makes another subscription.\n\n**Local Compose receiver:** add `\"secret\":\"local-demo-webhook-secret-32-characters\"` to this body, matching the receiver WEBHOOK_DEMO_SECRET (use your configured value if different). The default generated secret otherwise will not match the demo receiver. Requires debug mode; hosted callbacks require your public HTTPS receiver.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event_types\": [\n    \"message_received\",\n    \"connection.stream_degraded\",\n    \"connection.stream_restored\"\n  ],\n  \"callback_url\": \"{{callback_url}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([201]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const data = pm.response.json(); if (data.id) pm.environment.set(\"subscription_id\", data.id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "fca08d57-da17-517a-ae8e-b5815cf3977d",
          "name": "Get subscription and delivery counts",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/subscriptions/{{subscription_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                "{{subscription_id}}"
              ]
            },
            "description": "Scope: `events:read`. Signing secret is not returned again."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "c3f71085-27e7-536c-9c79-5a8dd7e79786",
          "name": "Pause subscription",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/subscriptions/{{subscription_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                "{{subscription_id}}"
              ]
            },
            "description": "Scope: `events:write`. Cancels pending/sending deliveries and fences the listener if this was the last active subscription. Retains history.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"active\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "f5a364da-4b97-5146-94bf-1968a8c0bf08",
          "name": "Resume subscription",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/subscriptions/{{subscription_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                "{{subscription_id}}"
              ]
            },
            "description": "Scope: `events:write`. Requires a ready LinkedIn connection and resumes future callbacks.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"active\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "cdda4470-3c9f-52cf-b244-ff7df968f95e",
          "name": "Inspect listener health and gaps",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/listener",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "listener"
              ]
            },
            "description": "Scope: `events:read`. stream_status, connection_health, continuity_status, open_gap_count, last_frame_at, last_confirmed_at, and up to 50 gaps. Connected/recovered does not prove gap backfill."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "10 Events and deliveries",
      "description": "Inspect persisted event metadata and delivery history. Event detail can contain message content. Replay invokes the receiver again.",
      "item": [
        {
          "id": "3c7cc8b8-39e6-52ac-aa10-bac115a39956",
          "name": "List event metadata",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/events?offset={{event_offset}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "events"
              ],
              "query": [
                {
                  "key": "offset",
                  "value": "{{event_offset}}"
                }
              ]
            },
            "description": "Scope: `events:read`. Page size up to 100, offset 0–100000. Set event_offset to next_event_offset until it is blank/null. Copy the desired event ID manually."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const data = pm.response.json(); pm.environment.set(\"next_event_offset\", data.next_offset === null ? \"\" : String(data.next_offset));",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "f2dcf3a3-53b1-5f41-9b81-dd3fd141c28f",
          "name": "Get event including data",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/events/{{event_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "events",
                "{{event_id}}"
              ]
            },
            "description": "Scope: `events:read`. Includes decrypted normalized data, possibly message text."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "778e70cd-5751-5da5-8a97-74c2957b0890",
          "name": "List deliveries",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/subscriptions/{{subscription_id}}/deliveries?offset={{delivery_offset}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "subscriptions",
                "{{subscription_id}}",
                "deliveries"
              ],
              "query": [
                {
                  "key": "offset",
                  "value": "{{delivery_offset}}"
                },
                {
                  "key": "status",
                  "value": "{{delivery_status}}",
                  "disabled": true,
                  "description": "Optional status filter"
                }
              ]
            },
            "description": "Scope: `events:read`. Up to 100 per page; offset 0–100000. Enable the optional status query row to filter pending/sending/delivered/failed/canceled. Copy delivery_id manually."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const data = pm.response.json(); pm.environment.set(\"next_delivery_offset\", data.next_offset === null ? \"\" : String(data.next_offset));",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "b7f454be-8b2d-58c0-87b0-8d7efb997ac5",
          "name": "Get delivery and attempts",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/deliveries/{{delivery_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "deliveries",
                "{{delivery_id}}"
              ]
            },
            "description": "Scope: `events:read`. Delivery status, attempt/replay counts, safe errors, timestamps and attempt history."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "cce57583-0fa2-5278-b142-6c7f43556cbb",
          "name": "Replay delivery",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/deliveries/{{delivery_id}}/replay",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "deliveries",
                "{{delivery_id}}",
                "replay"
              ]
            },
            "description": "Scope: `events:write`. Explicit redelivery; also permitted for already delivered records. Requires an active subscription and no current send. Returns 202; inspect delivery afterward. This endpoint has no idempotency-key contract."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([202]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "11 Compatibility invitation API",
      "description": "Alternative invitation shape backed by the same durable operation system. These requests send real invitations, just like the typed send operation.",
      "item": [
        {
          "id": "e0bcfbba-7a98-5aa4-a120-b529598c5d02",
          "name": "Send invitation (async)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Prefer",
                "value": "respond-async",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/accounts/{{connection_id}}/linkedin/invite",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "accounts",
                "{{connection_id}}",
                "linkedin",
                "invite"
              ]
            },
            "description": "Scopes: `operations:write`, `linkedin:send`. account_id may be a connection UUID (used here) or LinkedIn username. Body: hash_id, optional message up to 300 characters, optional return_original (default false; raw diagnostic output). Async returns data.operation_id. Default mode waits briefly: 200 provider result, 202 pending, 424 failure, 409 unknown outcome. Poll X-Operation-Id for durable status.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"hash_id\": \"{{recipient_actor_id}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([202]).to.include(pm.response.code));",
                  "{",
                  "const data = pm.response.json();",
                  "const id = pm.response.headers.get(\"X-Operation-Id\") || (data.data && data.data.operation_id) || (data.error && data.error.details && data.error.details.operation_id);",
                  "if (id) pm.environment.set(\"operation_id\", id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "9b988ec0-361e-55f8-ad81-42aa0d1c12c9",
          "name": "Send invitation (wait briefly)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/accounts/{{connection_id}}/linkedin/invite",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "accounts",
                "{{connection_id}}",
                "linkedin",
                "invite"
              ]
            },
            "description": "Scopes: `operations:write`, `linkedin:send`. account_id may be a connection UUID (used here) or LinkedIn username. Body: hash_id, optional message up to 300 characters, optional return_original (default false; raw diagnostic output). Async returns data.operation_id. Default mode waits briefly: 200 provider result, 202 pending, 424 failure, 409 unknown outcome. Poll X-Operation-Id for durable status.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"hash_id\": \"{{recipient_actor_id}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "{",
                  "const data = pm.response.json();",
                  "const id = pm.response.headers.get(\"X-Operation-Id\") || (data.data && data.data.operation_id) || (data.error && data.error.details && data.error.details.operation_id);",
                  "if (id) pm.environment.set(\"operation_id\", id);",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "12 Connection maintenance",
      "description": "Credential/region updates invalidate authentication readiness. Disconnect clears saved sessions. Delete removes the connection and its history.",
      "item": [
        {
          "id": "b5f44360-7a27-52ba-bb0e-d99699d9ecfc",
          "name": "Replace account password",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}"
              ]
            },
            "description": "Scope: `connections:write`. Set new_linkedin_password. Requires idle connection; sets needs_login and invalidates Recruiter readiness. Submit a new Login with a new operation run afterward. Region can be included in the same PATCH.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"password\": \"{{new_linkedin_password}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const connection = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && connection.id && connection.provider) {",
                  "    pm.environment.set(\"connection_id\", connection.id);",
                  "    pm.environment.set(\"connection_health\", connection.health);",
                  "    if (connection.external_actor && connection.external_actor.id) {",
                  "        pm.environment.set(\"actor_id\", connection.external_actor.id);",
                  "    } else {",
                  "        pm.environment.unset(\"actor_id\");",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "cf86c1ef-5d14-53f5-a008-5f684d268185",
          "name": "Change account region",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}"
              ]
            },
            "description": "Scope: `connections:write`. Requires idle connection and Relay-provided proxy capacity in new_region. A changed region requires a new login; unchanged region is a no-op.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"region\": \"{{new_region}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const connection = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && connection.id && connection.provider) {",
                  "    pm.environment.set(\"connection_id\", connection.id);",
                  "    pm.environment.set(\"connection_health\", connection.health);",
                  "    if (connection.external_actor && connection.external_actor.id) {",
                  "        pm.environment.set(\"actor_id\", connection.external_actor.id);",
                  "    } else {",
                  "        pm.environment.unset(\"actor_id\");",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "7f8a84a8-70ab-58f7-a536-b6507f85504b",
          "name": "Disconnect and clear session",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/disconnect",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "disconnect"
              ]
            },
            "description": "Scope: `connections:write`. Clears saved LinkedIn sessions, disables subscriptions, cancels queued operations/pending deliveries, preserves event/delivery history. Can return 409 while busy. A later login does not reactivate subscriptions."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        },
        {
          "id": "d5bc637c-091c-5296-aae3-2f77b9dff222",
          "name": "Delete connection and history",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}"
              ]
            },
            "description": "Scope: `connections:write`. Deletes the connection and its event/delivery history. HTTP 204. Can return 409 while busy. Only send for a connection you intend to remove."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([204]).to.include(pm.response.code));"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "13 Optional synthetic smoke",
      "description": "No LinkedIn account required. Create a simulated connection, then use the keyed request for retry/replay or the keyless request to verify automatic key generation. Creation switches connection_id to the simulated connection; reselect your LinkedIn account before LinkedIn requests.",
      "item": [
        {
          "id": "df8b882c-5f7e-5be5-82a8-b843e75173d9",
          "name": "Create simulated connection",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections"
              ]
            },
            "description": "Scope: `connections:write`. Creates an isolated synthetic provider connection and saves its ID. Does not access LinkedIn.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"provider\": \"simulated\",\n  \"external_actor\": {\n    \"kind\": \"person\",\n    \"id\": \"postman-demo\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([201]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const connection = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && connection.id && connection.provider) {",
                  "    pm.environment.set(\"connection_id\", connection.id);",
                  "    pm.environment.set(\"connection_health\", connection.health);",
                  "    if (connection.external_actor && connection.external_actor.id) {",
                  "        pm.environment.set(\"actor_id\", connection.external_actor.id);",
                  "    } else {",
                  "        pm.environment.unset(\"actor_id\");",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "9a311653-2047-5e4b-aaa7-6fdd65eb1dd1",
          "name": "Record synthetic value",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{request_idempotency_key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `simulated.record`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\nSynthetic local contract: input contains a string `value`.\n\nUse only with the simulated connection. Poll and then repeat this POST unchanged to check idempotent replay.\n\nThis request queues a durable operation. HTTP 202 means accepted, not completed. It saves `operation_id`; open **03 Operations / Get operation** and click Send until terminal. Provider output is in `result`; inspect `error_code` on failure.\n\n**Idempotency:** Send again with unchanged input to replay the same operation. Clear `operation_run_id` in the selected environment before an intentional new run or page. A nonempty `idempotency_key` overrides the generated key; change or clear that override yourself. Never start a new send merely because its outcome is unknown.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"simulated.record\",\n  \"input\": {\n    \"value\": \"Postman smoke test\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP status\", () => pm.expect([200, 202]).to.include(pm.response.code));",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "const operation = pm.response.json();",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && operation.id && operation.capability) {",
                  "    pm.environment.set(\"operation_id\", operation.id);",
                  "    pm.environment.set(\"operation_status\", operation.status);",
                  "    if (operation.challenge && operation.challenge.id) {",
                  "        pm.environment.set(\"challenge_id\", operation.challenge.id);",
                  "    } else {",
                  "        pm.environment.unset(\"challenge_id\");",
                  "    }",
                  "    if (operation.status === \"succeeded\" && operation.result) {",
                  "        const result = operation.result;",
                  "        if (result.actor_id) pm.environment.set(\"actor_id\", result.actor_id);",
                  "        if (operation.capability === \"linkedin.conversations.list\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (operation.capability === \"linkedin.conversations.search\" && Object.prototype.hasOwnProperty.call(result, \"next_cursor\")) {",
                  "            pm.environment.set(\"next_conversation_search_cursor\", result.next_cursor || \"\");",
                  "        }",
                  "        if (Object.prototype.hasOwnProperty.call(result, \"next_start_index\")) {",
                  "            pm.environment.set(\"next_sent_invitation_start\", result.next_start_index === null ? \"\" : String(result.next_start_index));",
                  "        }",
                  "    }",
                  "}",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "id": "6d0e8516-6684-4c11-a7ee-d1d9cb97a6ec",
          "name": "Record synthetic value without key",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/connections/{{connection_id}}/operations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "connections",
                "{{connection_id}}",
                "operations"
              ]
            },
            "description": "**Capability:** `simulated.record`\n\n**Scopes:** `operations:write` to submit, `operations:read` to poll.\n\nUse after **Create simulated connection**. This request intentionally omits `Idempotency-Key`, so Relay generates and returns one in the response header. Each click on Send creates a new operation, even with the same body. The test saves the operation ID and returned key; poll **03 Operations / Get operation** for the final result. This synthetic request does not access LinkedIn.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"capability\": \"simulated.record\",\n  \"input\": {\n    \"value\": \"Postman smoke test\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"Expected HTTP 202\", () => pm.response.to.have.status(202));",
                  "if (pm.response.code === 202) {",
                  "    const operation = pm.response.json();",
                  "    const key = pm.response.headers.get(\"Idempotency-Key\");",
                  "    pm.test(\"Operation ID returned\", () => pm.expect(operation.id).to.be.a(\"string\").and.not.empty);",
                  "    pm.test(\"Generated key returned\", () => pm.expect(key).to.match(/^auto-[0-9a-f-]{36}$/));",
                  "    if (operation.id) {",
                  "        pm.environment.set(\"operation_id\", operation.id);",
                  "        pm.environment.set(\"operation_status\", operation.status);",
                  "    }",
                  "    if (key) pm.environment.set(\"last_idempotency_key\", key);",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}
