If you're building an internal tool for vendor sourcing, CRM enrichment, or partnership discovery, pulling agency data from TopDevelopers.co programmatically beats manual research the same way any API beats manual browsing but the interesting part isn't the extraction, it's what you do with the enrichment layer once you have it. This post covers the actor's input/output schema, two full working integration examples, and a few practical patterns for using this as part of a larger pipeline rather than a one-off pull.
Most agency-directory scrapers stop at raw listing data name, rating, maybe a website. What makes this API worth integrating rather than just running manually through the Apify Console is the enrichment layer: a real email pulled from the agency's own site rather than a directory contact form, and an insights object that turns unstructured review text into something you can actually filter and sort on programmatically.
Authentication
Like any Apify actor, this runs through the standard Apify REST API. You'll need an API token from your Apify account under Settings → Integrations, passed either as a Bearer header or a query parameter depending on which endpoint you're calling.
Input schema

At least one of searchQuery, companyName, or selectedDomain must be set.
**Starting a run Python*
import requests
api_token = 'YOUR_APIFY_API_TOKEN'
actor_id = 'techforce.global~it-agency-lead-finder-enricher-topdevelopers-co'
response = requests.post(
f'https://api.apify.com/v2/acts/{actor_id}/runs',
headers={'Authorization': f'Bearer {api_token}'},
json={
'searchQuery': 'Flutter developers in UAE',
'maxResults': 50,
'maxReviewsPerCompany': 5
}
)
dataset_id = response.json()['data']['defaultDatasetId']
Fetching and filtering results
import time
def wait_for_run(run_id, token):
while True:
status = requests.get(
f'https://api.apify.com/v2/actor-runs/{run_id}',
params={'token': token}
).json()['data']['status']
if status == 'SUCCEEDED': return True
if status in ('FAILED','ABORTED','TIMED-OUT'): return False
time.sleep(5)
agencies = requests.get(
f'https://api.apify.com/v2/datasets/{dataset_id}/items',
params={'token': api_token}
).json()
top_agencies = [a for a in agencies if a.get('rating', 0) >= 4.5 and a.get('email') != 'NA']
print(len(top_agencies), 'qualified agencies with email')
Node.js pushing enriched profiles to a CRM
const { ApifyClient } = require('apify-client');
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor(
'techforce.global/it-agency-lead-finder-enricher-topdevelopers-co'
).call({
selectedDomain: 'Ecommerce Development',
selectedCategory: 'platform:shopify',
maxResults: 30
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const withBudgetFit = items.filter(a =>
a.insights?.common_project_budgets?.some(b => b.includes('$10,001'))
);
await fetch('https://your-crm.example.com/webhook/vendors', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(withBudgetFit)
});
Filtering on the insights object
The insights.common_project_budgets and insights.top_project_types fields are arrays of strings rather than structured ranges, since they're derived from natural-language review content. Matching on substring, as in the Node example above, is the practical approach checking whether a budget bracket string like "$10,001 - $50,000" appears in the array rather than trying to parse them into strict numeric ranges, which risks breaking if the underlying review phrasing varies.
This matters for anyone building automated scoring on top of the raw data: treat insights fields as signals to combine with your own weighting logic, not as a substitute for a full lead-score calculation. A practical middle ground is a simple point system award points for rating above a threshold, more points for a matching budget bracket, more again for a matching project type and sort by total rather than trying to build a single authoritative score into the pipeline itself.
Handling the two-tier pricing in code
Since basic (listing-only) and enriched (full profile) results are priced differently, a cost-conscious integration pattern is to run a broad basic search first to map out the category, then a second, narrower enriched run against just the shortlist that passed initial filtering — rather than enriching every result from the first pass. This mirrors the manual research pattern of browsing broadly first and only digging deep on serious candidates, just automated.
In practice this means two API calls chained together: the first with a higher maxResults and no need for maxReviewsPerCompany depth, the second with a much smaller maxResults (just the shortlist) but a higher maxReviewsPerCompany, since review depth matters more once you're down to serious candidates.
Common integration patterns
Manual pull a BD or procurement team member runs a search through the Apify Console directly and downloads CSV for immediate use, no code required
Scheduled pipeline a cron job or n8n workflow re-runs key categories monthly or quarterly, refreshing a CRM's vendor table automatically
On-demand internal tool an internal sourcing tool calls the API in the background when a user searches, so end users never need to know Apify is involved
Two-stage enrichment a broad basic run followed by a narrow enriched run against the resulting shortlist, as described above, to control cost on large category sweeps
Error handling
As with any scraping-based actor, individual runs can fail due to transient issues an unusually specific query returning no matches, or a temporary network issue on the source site. Explicitly checking for FAILED or ABORTED status rather than assuming every run reaches SUCCEEDED avoids silent failures in a scheduled pipeline going unnoticed. It's also worth logging the input parameters alongside any failure, since a query that returns zero matches often indicates a category name that doesn't quite match TopDevelopers' own taxonomy rather than an actual system failure.
Rate limits and concurrency
The maxConcurrency setting controls how many agency profiles are processed simultaneously within a single run, but if you're running multiple separate API calls in parallel say, one per domain it's worth staggering their start times slightly rather than firing all of them at once, to avoid hitting your account's overall concurrent-run limit, which varies by Apify plan tier.
Frequently asked
*Is there a sandbox for testing integration code without spending on real results? *
Running against a narrow companyName lookup for a single known agency is the practical equivalent real data, minimal cost, enough to validate your parsing logic.
*Can I run multiple domains in parallel? *
Each run is scoped to one search configuration; running separate parallel API calls for different domains works fine and is the standard pattern for broad multi-category research.
*What's a reasonable maxReviewsPerCompany for a first test? *
Something small, like 3-5, is enough to confirm the reviews array structure without spending on a full review pull across every result.
*Does the API support pagination for very large result sets? *
Use the standard Apify dataset offset/limit query parameters when fetching items rather than assuming a single request returns everything, particularly for runs near the 200-result cap.
Getting started
Full documentation and the interactive input schema are on the Apify listing: apify.com/techforce.global/it-agency-lead-finder-enricher-topdevelopers-co
For a first integration test, start with a companyName lookup against one agency you already know, confirm the output shape matches what's documented above, then move to a broader searchQuery or selectedDomain run once your parsing logic is confirmed working end to end.


Top comments (0)