Post-mortem · August 10, 2026 · 5 min read

An API that silently ignores a field
is lying to you.

Exactly one person outside my own account has ever evaluated this API. They sent a field name I do not accept. It was ignored without a word, they were told they looked automated three times inside five minutes, and they left. I only found out two weeks later, reading the database for something else.

What actually happened

On 26 July someone found useHUMA on an API marketplace and tried it. Three calls: two eleven seconds apart, then one more almost five minutes later, then nothing. This is what they sent:

{ "key_count": 18, "mouse_moves": 55, "time_on_page_ms": 3200 }

mouse_moves is not a field this API reads. The real name is mouse_sample_count. So their 55 mouse movements arrived, were not recognised, and were dropped. The visitor was then scored as a visitor who had produced no pointer movement at all, because from the server's point of view that is exactly what the payload said.

They got back 0.3 out of 1. Three times, identical. Then they closed the tab. From their side the product looked broken or stupid. From my side, nothing looked wrong at all: the request was well formed, it returned 200, and the score was correct for the data it received.

The failure mode is not that the API rejected them. It is that the API agreed with them. It accepted the request, answered confidently, and never mentioned that most of what they sent had gone in the bin.

Where the wrong name came from

I went looking for where they got mouse_moves, half expecting a typo. It came from my own marketplace listing. The request example on the endpoint page used a field name the API does not accept, and had done since the listing went up.

So the sequence was: they copied my example, my example was wrong, my API ignored the result in silence, and my scoring did what it should have done with an empty payload. Four correct-looking steps, one lost evaluation. Nobody threw an error at any point.

There is a general version of this and it is worth stating plainly. Any API that takes a free-form object and reads a known subset of it has this bug by default. Extra keys are usually harmless. Extra keys that were meant to be the important ones are not, and the caller has no way to tell the two apart.

The fix

Verification responses now carry a warnings array whenever the payload contains something the API did not read. That developer's exact request now answers:

"warnings": [
  "Ignored 1 unrecognised field in sessionData: mouse_moves
   (did you mean mouse_speed_cv, mouse_direction_changes,
   mouse_sample_count?). Field reference:
   https://humaverify.com/docs#session-data"
]

Two details in there mattered more than I expected while building it.

It suggests a list, not a best guess. My first version insisted on picking the single closest field name, and for mouse_moves it returned nothing at all, because three real fields start with the same word and the tie-break threw them all out. The input is genuinely ambiguous. Naming the candidates is more useful than guessing, and it cannot be confidently wrong.

It stays quiet when it should. The collector emits a handful of fields the scorer does not read today. Warning about those would fire on every correct integration, which is worse than the silence it replaces. A warning that cries wolf gets filtered out of the logs within a week.

What I would take from this if it were not mine

  1. Silence is a design decision, not a default. Ignoring an unknown field is a choice to withhold the one piece of information the caller needs to fix their integration. It costs a few lines to say so.
  2. Your own examples are part of your API. They are not documentation around the product, they are the first code anyone runs. Mine was wrong for months and it never occurred to me to test it, because examples do not fail CI.
  3. A correct answer to the wrong input is still a wrong answer. The score that developer received was arithmetically right and completely useless. Correctness at the function level says nothing about correctness at the product level.
  4. Find out sooner than two weeks. There was no alert, no dashboard, no metric. I found it by reading rows for an unrelated reason. That is luck, and luck does not scale.

The honest footnote

I could tell this story as a win. It is not one. Somebody took the time to try a product from a person they had never heard of, and the product told them they were a robot because of a mistake I had published myself. They are not coming back, and I have no way to reach them: the marketplace shows me a username and nothing else.

The fix does not recover that. It only means the next person gets told what went wrong while they still have the tab open. That is the whole improvement, and it was worth writing down because the failure was invisible from the inside, which is the kind most likely to still be running in your own product right now.

The page that lists what this does not catch.

Where useHUMA is the wrong tool and where it stops on purpose, including the cases where the honest recommendation is a competitor.

Read the limitsTry the demo
Jaime Trejo, building useHUMA alone · All notes
Help