Export Events to CSV
Paginate and export visitor data to CSV with multi-day chunking
Steps
1. Choose Your Fields
Use select to return only the fields you need. This reduces response size and makes the CSV cleaner.
select=first_name,last_name,email,company_name,company_domain,job_title,event_data,timestamp
Fields that are null for a given row are omitted from the response. See the Events API schema endpoint for all available fields.
2. Export with Pagination
The API returns a maximum of limit rows per request. Use offset to paginate.
import csv
import time
import requests
API_KEY = "your_api_key"
API_SECRET = "your_api_secret"
PIXEL_ID = "your_pixel_id"
HEADERS = {
"X-Api-Key": API_KEY,
"X-Api-Secret": API_SECRET,
}
FIELDS = [
"first_name", "last_name", "email", "current_business_email",
"company_name", "company_domain", "job_title", "department",
"seniority_level", "company_industry", "company_employee_count_range",
"linkedin_url", "event_data", "timestamp",
]
# Last 24 hours
end_ms = int(time.time() * 1000)
start_ms = end_ms - (24 * 60 * 60 * 1000)
all_rows = []
offset = 0
limit = 100
while True:
resp = requests.get(
"https://api.delivr.ai/api/v3/events/resolution_full_profile",
headers=HEADERS,
params={
"source": "pixel",
"pixel_id": PIXEL_ID,
"start_ms": start_ms,
"end_ms": end_ms,
"limit": limit,
"offset": offset,
"filter": "resolved:eq:true",
"select": ",".join(FIELDS),
"orderby": "timestamp:desc",
},
)
data = resp.json()
rows = data.get("rows", [])
all_rows.extend(rows)
if len(rows) < limit:
break # No more rows
offset += limit
# Write CSV
with open("visitors.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=FIELDS, extrasaction="ignore")
writer.writeheader()
for row in all_rows:
writer.writerow(row)
print(f"Exported {len(all_rows)} rows to visitors.csv")Multi-Day Export
The Events API has a 25-hour maximum time window per request. For longer ranges, loop through 24-hour chunks.
import csv
import time
import datetime
import requests
API_KEY = "your_api_key"
API_SECRET = "your_api_secret"
PIXEL_ID = "your_pixel_id"
HEADERS = {
"X-Api-Key": API_KEY,
"X-Api-Secret": API_SECRET,
}
FIELDS = [
"first_name", "last_name", "email", "current_business_email",
"company_name", "company_domain", "job_title", "timestamp",
]
ONE_DAY_MS = 24 * 60 * 60 * 1000
DAYS_BACK = 7
now_ms = int(time.time() * 1000)
all_rows = []
for day in range(DAYS_BACK):
end_ms = now_ms - (day * ONE_DAY_MS)
start_ms = end_ms - ONE_DAY_MS
offset = 0
while True:
resp = requests.get(
"https://api.delivr.ai/api/v3/events/resolution_full_profile",
headers=HEADERS,
params={
"source": "pixel",
"pixel_id": PIXEL_ID,
"start_ms": start_ms,
"end_ms": end_ms,
"limit": 100,
"offset": offset,
"filter": "resolved:eq:true",
"select": ",".join(FIELDS),
},
)
rows = resp.json().get("rows", [])
all_rows.extend(rows)
if len(rows) < 100:
break
offset += 100
date_str = datetime.datetime.fromtimestamp(
start_ms / 1000, tz=datetime.timezone.utc
).strftime("%Y-%m-%d")
print(f" {date_str}: fetched to offset {offset + len(rows)}")
with open("visitors_7day.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=FIELDS, extrasaction="ignore")
writer.writeheader()
for row in all_rows:
writer.writerow(row)
print(f"Exported {len(all_rows)} rows to visitors_7day.csv")Variations
Deduplicated Export (One Row Per Person)
Add distinct=hem to get one row per unique visitor instead of one row per page view:
params={
"source": "pixel",
"pixel_id": PIXEL_ID,
"start_ms": start_ms,
"end_ms": end_ms,
"limit": 100,
"offset": offset,
"filter": "resolved:eq:true",
"distinct": "hem",
"has_valuable_data": "true",
"select": ",".join(FIELDS),
}Deduplicated by Company
One row per unique company:
"distinct": "company_domain",
"has_valuable_data": "true",Sort Order
Use orderby to control row order:
orderby=timestamp:desc # Newest first
orderby=timestamp:asc # Oldest first
Notes
- The
selectparameter only returns fields that have values. If a field is null for a row, it's omitted from the response. Your CSV writer should handle missing keys gracefully (theextrasaction="ignore"andDictWriterhandle this). offsetpagination with no overlap is confirmed. Each page returns distinct rows.- To enrich exported visitors with your own data provider, add
hemtoselect. It is the hashed email the visit resolved to, which is not always the person's primary email. See Include the Hashed Email for Enrichment. - For very large exports (10,000+ rows per day), consider adding a short delay between requests to avoid rate limits.
- The
has_valuable_dataparameter filters to rows with a populated profile. It keeps a row only when all four of these hold: an email of some kind (business, personal, or flagged as business); an email address or a company name; a first name or a company name; and a last name. A row carrying only a business address does not qualify.
Next Steps
- On-Domain Events API: full API reference (filters, fields, schema)
- High-Intent Visitors: filter exports to pricing/demo page visitors
- Intent Audiences API: create audiences from intent topics instead of pixel data
Updated 10 days ago
Did this page help you?
