logo-darkPipe0

Search then enrich

The point of this pattern is that a search response is already a valid pipe input. You don't have to reshape anything in between. Search for a list of people, then hand search.results directly to a pipes request to enrich every row.

This example finds senior software-development people, then resolves a work email and mobile number for each of them.

import { Pipe0 } from "@pipe0/client";

const pipe0 = new Pipe0({ apiKey: process.env.PIPE0_API_KEY });

// 1. Search for records.
const search = await pipe0.searches.search({
  config: {
    environment: "production",
  },
  search: {
    search_id: "people:profiles:amplemarket@2",
    config: {
      limit: 10,
      filters: {
        current_employer_linkedin_industries: [
          "Software Development",
        ],
        current_seniority_levels: [
          "C-Suite",
          "VP",
          "Head",
          "Director",
        ],
      },
    },
  },
});

// 2. Feed the search results straight into the enrichment request.
const enriched = await pipe0.pipes.pipe({
  config: {
    environment: "production",
  },
  pipes: [
    {
      pipe_id: "person:workemail:profileurl:waterfall@1",
    },
    {
      pipe_id: "person:mobile:profileurl:waterfall@1",
    },
  ],
  input: search.results,
});
console.log(enriched);
import requests

headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

# 1. Search for records.
search = requests.post(
    "https://api.pipe0.com/v1/search/run/sync",
    headers=headers,
    json={
        "config": {
            "environment": "production",
        },
        "search": {
            "search_id": "people:profiles:amplemarket@2",
            "config": {
                "limit": 10,
                "filters": {
                    "current_employer_linkedin_industries": [
                        "Software Development",
                    ],
                    "current_seniority_levels": [
                        "C-Suite",
                        "VP",
                        "Head",
                        "Director",
                    ],
                },
            },
        },
    },
).json()

# 2. Feed the search results straight into the enrichment request.
enriched = requests.post(
    "https://api.pipe0.com/v1/pipes/run/sync",
    headers=headers,
    json={
        "config": {
            "environment": "production",
        },
        "pipes": [
            {
                "pipe_id": "person:workemail:profileurl:waterfall@1",
            },
            {
                "pipe_id": "person:mobile:profileurl:waterfall@1",
            },
        ],
        "input": search["results"],
    },
).json()
print(enriched)
# 1. Search and capture the results array.
RESULTS=$(curl -s -X POST "https://api.pipe0.com/v1/search/run/sync" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "config": {
    "environment": "production"
  },
  "search": {
    "search_id": "people:profiles:amplemarket@2",
    "config": {
      "limit": 10,
      "filters": {
        "current_employer_linkedin_industries": [
          "Software Development"
        ],
        "current_seniority_levels": [
          "C-Suite",
          "VP",
          "Head",
          "Director"
        ]
      }
    }
  }
}' | jq '.results')

# 2. Enrich, feeding the search results in as the input array.
curl -X POST "https://api.pipe0.com/v1/pipes/run/sync" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --argjson rows "$RESULTS" '{
  "config": {
    "environment": "production"
  },
  "pipes": [
    {
      "pipe_id": "person:workemail:profileurl:waterfall@1"
    },
    {
      "pipe_id": "person:mobile:profileurl:waterfall@1"
    }
  ]
} + { input: $rows }')"

How it fits together

  • The search outputs name, job_title, profile_url and company_domain for each person.
  • Passing search.results as the pipe input works because search results are returned as fully expanded field values. The API accepts them directly.
  • The two waterfall pipes read each row's profile_url and add work_email and mobile.

For large result sets, swap pipes.pipe for pipeInBatches. It splits search.results into chunks and runs them with bounded concurrency, so the same code handles 10 rows or 10,000.