Automated tests for the inputs you didn't think of.
unexpectedd reads your API's code, generates the edge cases, malformed payloads and abuse scenarios your tests skipped, runs them against a sandboxed copy of your app, and turns every real break into a failing test you can commit.
Now onboarding design partners. Python and FastAPI first.
The bugs that pass code review
Your tests check the cases you imagined. These are the ones that ship. Every row below is the kind of finding unexpectedd is built to produce: the exact input, and what your API did with it.
| Kind | Input it tried | What happened |
|---|---|---|
| Boundaries | quantity = -3 | Order total went negative |
| Malformed payloads | {"email": null} | 500 error with a stack trace in the response body |
| Authorization | User B requests GET /invoices/41, owned by user A | 200, full invoice returned |
| State sequences | Delete the account, then reuse its old token | Token still accepted |
| Encoding | name = "Zoƫ\u0000" | Row saved, silently missing from search |
| Concurrency | Two POST /coupons/redeem calls 5 ms apart | Single-use coupon redeemed twice |
How it works
A language model decides what is worth trying. A property-based engine does the trying. You only see what it can reproduce.
-
Read
Point it at your repository. It reads your routes, Pydantic models, validators, auth dependencies and OpenAPI schema.
-
Hypothesize
Claude works out the rules your API should never break: totals stay positive, users only see their own data, deleted means gone.
-
Search
Hypothesis generates thousands of inputs and request sequences against an in-process copy of your app, then shrinks each failure to its smallest form.
-
Report
Each confirmed break comes back as a failing pytest, the file and line behind it, and a plain-English explanation. In CI, as a pull request.
Built to be safe to run
- It tests your app, not your servers. By default it boots your app in-process with a test client. Staging URLs work only after you prove you own the domain.
- No finding without a reproduction. If it can't write a test that fails, it doesn't report it. Noise is the reason teams turn testing tools off.
- Nothing lands without your review. It never pushes to your branches. New tests arrive as a pull request you can read, change or close.
Get early access
We're opening early access to a small group of teams that run Python APIs in production. Join the waitlist and we'll email you when your spot opens.