Blog/Sales & enrichment
12 min read

A Wrong Enum Returns Zero: Ploid and Prompt-Shaped APIs

A wrong enum returned 0 rows. A wrong range format returned 160,884. Neither raised an error. Why prompt-shaped APIs like Ploid exist, and what they cost.

A Wrong Enum Returns Zero: Ploid and Prompt-Shaped APIs

Here are three searches for the same people. Same job title, same intent, one field different each time.

seniority "vp",             size "51,200"  ->  28,417 people
seniority "vice_president", size "51,200"  ->       0 people
seniority "vp",             size "51-200"  ->  160,884 people

None of the three returned an error. The middle one is a wrong enum value, and it comes back as a clean empty result set that looks exactly like "nobody matches." The third one is a wrong range format, and rather than failing it silently drops the company size filter entirely, handing back six times the rows with no indication that a constraint went missing.

That is the shape of a filter API, and it is the reason a different shape is appearing. Ploid is one of the clearer examples: instead of a filter object it takes a sentence and a spending cap.

Fair disclosure. You are on the Monid blog, Monid sells access to the filter-shaped APIs described below, and Ploid is a content partner of ours. Ploid is not in the Monid catalogue. The section near the end argues for the shape we sell, because on most days it is still the right one.

Why did my search return zero when the filter looked right?

Because the filter was not validated against anything. It was accepted, applied, and matched nothing.

The runs above use apollo /mixed_people/api_search, which is free to search and therefore easy to probe. The query is otherwise identical: person_titles[] of "VP of Sales", a company size band, five results per page.

monid run -p apollo -e /mixed_people/api_search \
  --query '{"person_titles[]":["VP of Sales"],"person_seniorities[]":["vp"],"organization_num_employees_ranges[]":["51,200"],"per_page":5}' \
  -w -o people.json

Swap vp for vice_president and total_entries goes to zero. Both strings are reasonable English for the same idea. Only one is in the enum, which runs owner, founder, c_suite, partner, vp, head, director, manager, senior, entry, intern. You can read that list in the schema, and you have to, because the API will not tell you.

The size format is worse. 51,200 is the documented form and returns 28,417. 51-200 is what most people would write first, and it returns 160,884: every VP of Sales regardless of company size. The filter did not fail, it evaporated.

This is the failure mode that matters. A crash you notice. A zero you investigate. A plausible number that quietly answers a different question than the one you asked is the one that reaches a spreadsheet, then a campaign, then a quarterly number.

It is worth proving rather than assuming. Run the same query with the size filter removed entirely:

monid run -p apollo -e /mixed_people/api_search \
  --query '{"person_titles[]":["VP of Sales"],"person_seniorities[]":["vp"],"per_page":5}' \
  -w -o nosize.json

That returns 160,884, matching the hyphenated run exactly. The filter was not loosened or reinterpreted. It was discarded, and the API answered a question with one fewer constraint than the one asked.

The same query three times, one field different, three very different answers and no error on any of them.
The same query three times, one field different, three very different answers and no error on any of them.

The cost of using a filter API correctly is knowing its taxonomy: which enums exist, which are case sensitive, which formats are accepted, which combinations are mutually exclusive. That knowledge is real work, it is per vendor, and it does not transfer. We wrote up the practical version for PDL and the Apollo specifics separately, and the reason those posts exist at all is that this knowledge has to be written down somewhere.

How do you catch this before it reaches a campaign?

Three habits, all cheap, all derived from the runs above.

Predict the magnitude first. Before reading a single row, say out loud roughly how many people you expect. Tens of thousands of VPs of Sales at mid sized companies is plausible. A hundred and sixty thousand is not, and neither is zero. total_entries is the cheapest assertion available and most integrations never look at it.

Probe by removal. When a number surprises you, delete one field and re-run. If the count does not move, that field was doing nothing, which is exactly what the hyphen case looks like. On an endpoint where search is free this costs nothing but a minute.

Read the enums from the schema, not from the docs page. monid inspect -p apollo -e /mixed_people/api_search prints the accepted values inline, including that person_seniorities[] runs owner, founder, c_suite, partner, vp, head, director, manager, senior, entry, intern and nothing else. Inspecting is free, and it is the step that would have caught vice_president before it cost anybody an afternoon.

The general shape of that last habit is why the discover and inspect steps exist at all: a schema you can read at run time turns a taxonomy problem into a lookup. That is the same benefit prompt-shaped APIs are chasing, reached from the other direction.

For agents

Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:

set up https://monid.ai/SKILL.md

It learns the discover, inspect and run workflow itself. More detail in the agent quickstart.

For humans

npm install -g @monid-ai/cli
monid keys add --label main --key <your-api-key>

More detail in the CLI quickstart.

Give this to your agent

$Set up https://monid.ai/SKILL.md, and then use Monid to find VPs of Sales at companies with 51 to 200 employees, and tell me which filter values you used.

What does an API look like when you send a prompt instead?

It takes the sentence and a budget, and decides the query itself.

Everything in this section is read from Ploid's public documentation rather than measured, because Ploid is not in our catalogue and we have not run it. Their POST /v1/agent takes a natural language prompt, a max_acu cap, a response_format, and an optional output_schema for structured output. Auth is a bearer token, base URL https://api.ploid.com/v1.

The interesting field is max_acu. Their own docs describe it as "an Agent admission and billing limit," not a compute ceiling, and the error surface includes insufficient_acu, daily_budget_exceeded and monthly_budget_exceeded. That is a lot of budget machinery for one endpoint.

It is there because it has to be. Once the service decides how many searches to run, you no longer know what a request costs before you send it. A filter API is priced by arithmetic: results requested times price per result. A prompt-shaped API has no such arithmetic, so the cap has to move into the request. max_acu is not a convenience feature, it is the thing that makes the shape usable at all.

They also expose narrower surfaces alongside it: a Search API for synchronous retrieval of up to 100 results, an Enrichment API for resolving known identities, and People Sets for durable lists. That layering is the honest design. The agent endpoint is the top of a stack, not a replacement for it.

The pitch behind all of it is what they call the Living Index, a people index that refreshes as roles change. Freshness is a real axis and we have argued elsewhere that recency beats coverage for anything you act on, so we are not going to pretend that claim is novel. What is novel here is the request shape.

Who should own the query planning?

That is the whole question, and both answers are defensible.

Filter APIPrompt-shaped API
Who writes the queryYou, against a taxonomyThe service, from a sentence
Failure modeSilent zero, or a silently dropped filterPlausible answer to a misread intent
Cost before you sendKnown by arithmeticBounded by a cap, not known
Same input twiceSame rowsNot guaranteed
DebuggingRead the filterRead whatever it tells you it did
OnboardingLearn the enumsWrite a sentence

Notice the failure modes are not the same defect in different clothes. A filter API fails at the edge, where your vocabulary meets its taxonomy. A prompt-shaped API fails in the middle, where its interpretation of your sentence meets its own index. The first is discoverable by reading a schema. The second is discoverable only by checking the output, which is why every serious implementation returns some account of what it actually did.

This is also the argument Monid is built on, one layer up. An agent says what it needs in plain language, monid discover returns candidate endpoints with prices, monid inspect returns the schema, and the agent picks. The planning moves to the caller, but the taxonomy lookup does not stay manual. That middle position is deliberate, and we have written about why the marketplace shape suits agents and where MCP fits against a plain API.

Where each shape breaks: a filter API fails at your vocabulary, a prompt-shaped API fails at its own interpretation.
Where each shape breaks: a filter API fails at your vocabulary, a prompt-shaped API fails at its own interpretation.

What does each shape cost you?

Not the price. The predictability.

A per result filter API gives you an exact number before you send: rows requested times the per row price, and Apollo's search step happens to be free entirely, with the charge arriving when you take contact data. That predictability is why finance teams tolerate usage billing at all.

A prompt-shaped API cannot offer that, so it offers a ceiling instead. You know the worst case and not the actual. For a nightly job that is fine. For a per user feature in your product, a ceiling is a different risk than a price, and it wants a different kind of monitoring.

The broader argument for paying per call rather than a subscription applies to both shapes and is written up separately. Current magnitudes for anything in our catalogue live on monid.ai/tools, because a number written into an article goes stale quietly.

One point in the prompt-shaped column that is easy to miss: the taxonomy work disappears from your side of the boundary. Whether that is a saving depends entirely on how many vendors you are integrating. For one vendor, learning the enums once is cheap. For six, it is most of the project, and enriching across several sources is where that cost actually shows up.

When is a filter API still the right answer?

Most of the time, and the reasons are concrete.

When you need the same rows twice. A filter is a specification. Run it Monday and Thursday and you get the same population plus whatever changed in the world. A prompt is an instruction, and nothing guarantees the same decomposition twice. Anything feeding a report or a diff wants the filter.

When the query is already precise. "Everyone at these 40 domains with a verified email" is not a sentence that benefits from interpretation. You know exactly what you want, the taxonomy expresses it exactly, and a natural language layer can only add a chance of being misread.

When you have to defend the list. Filters audit. Someone asks why a person is in the campaign and the answer is a query you can show them. "The agent decided" is a worse answer in a compliance conversation.

When the taxonomy is small. The whole argument above collapses if learning the enums takes ten minutes. Read the schema, write it down, move on. The LinkedIn scraper comparison is a case where the field lists are the entire decision.

We sell the filter-shaped ones, so treat that list with the suspicion it deserves. The honest summary is that prompt-shaped APIs are earlier, less predictable and better at exploration, and that exploration is a real job which filters serve badly. The two are not competing for the same request.

Conclusion

The best interface is the one whose failure mode you can live with. Filters fail loudly at the edges and silently in the middle of a range format, and the fix is reading the schema. Prompt-shaped APIs like Ploid's fail by answering a slightly different question well, and the fix is reading the output.

The rule worth keeping: if you cannot state the query as a filter, a prompt-shaped API is doing real work for you. If you can, it is adding a layer of interpretation between you and a result you already knew how to ask for. Start every integration by finding out which of those two you are in, and check total_entries against a number you expect before you trust a single row.

FAQ

Apify got barred from scraping Apollo. What should I use to pull fresh leads instead?

Use Apollo's own search endpoint rather than a scraper pointed at it, which is what the call in this article does, and reach for a different provider when you need fields Apollo does not expose. The full comparison of what replaced the scraping route is in the Apify alternatives guide and the Apollo specifics.

Will a prompt-shaped API give me the same results twice?

Not guaranteed, and you should design as if it will not. The service chooses how to decompose your sentence and how many passes to run, and both can change with the index, the model behind it, or your budget cap. If you need a stable population, express it as a filter and store the filter, not the results.

Does Monid carry Ploid?

No. Ploid is not in the Monid catalogue at the time of writing, and everything in this article about their API is read from their public documentation rather than measured. The people endpoints we do carry sit under people enrichment and Apollo.

Which shape should I hand an MCP agent?

Give it the filter API plus the ability to read the schema. An agent that can call inspect before it calls run gets the discoverability that makes prompt-shaped APIs attractive, while keeping a query it can show you afterwards. That combination is the point of the marketplace shape, and it is why turning a raw list into real people works the same way whichever vendor answers.

Last updated August 2026.

people search apiagentic apiprospectingai agents