Overview
Pipes add fields to your input records: a work email, a phone number, a full company profile. You pick pipes from the pipe catalog, send them with your input, and read the new fields off the response.
Run a pipe
This request enriches one input object. The pipe person:workemail:waterfall@1 reads name and company_domain and adds a work_email field.
import { Pipe0 } from "@pipe0/client";
const pipe0 = new Pipe0({ apiKey: process.env.PIPE0_API_KEY });
const result = await pipe0.pipes.pipe({
pipes: [
{
pipe_id: "person:workemail:waterfall@1",
},
],
input: [
{
id: "1",
name: "Jane Doe",
company_domain: "pipe0.com",
},
],
});
console.log(result);import requests
response = requests.post(
"https://api.pipe0.com/v1/pipes/run/sync",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"pipes": [
{
"pipe_id": "person:workemail:waterfall@1",
},
],
"input": [
{
"id": "1",
"name": "Jane Doe",
"company_domain": "pipe0.com",
},
],
},
)
print(response.json())curl -X POST "https://api.pipe0.com/v1/pipes/run/sync" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pipes": [
{
"pipe_id": "person:workemail:waterfall@1"
}
],
"input": [
{
"id": "1",
"name": "Jane Doe",
"company_domain": "pipe0.com"
}
]
}'The response contains one record per input object:
{
"id": "xgvxuqk2771d8t17n60vphu9",
"status": "completed",
"records": {
"1": {
"id": "1",
"fields": {
"work_email": {
"type": "string",
"value": "jane@pipe0.com",
"status": "completed"
// ...
}
// ...
}
}
}
// ...
}The full response carries more metadata than shown here. See the response object.
Stack pipes
Stack pipes in one request to build workflows. Each pipe reads the output of the pipes before it:
import { Pipe0 } from "@pipe0/client";
const pipe0 = new Pipe0({ apiKey: process.env.PIPE0_API_KEY });
const result = await pipe0.pipes.pipe({
pipes: [
{
pipe_id: "person:name:join@1",
},
{
pipe_id: "person:workemail:waterfall@1",
},
],
input: [
{
id: "1",
first_name: "Jane",
last_name: "Doe",
company_name: "Pipe0",
},
],
});
console.log(result);import requests
response = requests.post(
"https://api.pipe0.com/v1/pipes/run/sync",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"pipes": [
{
"pipe_id": "person:name:join@1",
},
{
"pipe_id": "person:workemail:waterfall@1",
},
],
"input": [
{
"id": "1",
"first_name": "Jane",
"last_name": "Doe",
"company_name": "Pipe0",
},
],
},
)
print(response.json())curl -X POST "https://api.pipe0.com/v1/pipes/run/sync" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pipes": [
{
"pipe_id": "person:name:join@1"
},
{
"pipe_id": "person:workemail:waterfall@1"
}
],
"input": [
{
"id": "1",
"first_name": "Jane",
"last_name": "Doe",
"company_name": "Pipe0"
}
]
}'person:name:join@1 creates name from first_name and last_name; the email pipe then reads name even though your input never contained it. Add run_if conditions to run pipes only for records that match, or templates to feed record fields into LLM prompts.
Enrich in bulk
The sync endpoint above waits for the result and suits small batches (fewer than 10 records). For larger inputs, create an async task with POST /v1/pipes/run (same payload), then poll GET /v1/pipes/check/{run_id} until status is completed.
const result = await fetch(`https://api.pipe0.com/v1/pipes/check/${runId}`, {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
});Read more about the trade-offs in sync vs async. The TypeScript client handles batching and polling for you.