Issue Nº 42 — Sep 25, 2026

The same error code covers a typo and an impossible ID range

Issue forty-two covers jokeapi, a keyless joke API in the Entertainment category. This session queried it live. A bad category and an out-of-range ID both come back as the same generic error. The catalogue holds 1,368 jokes, but English stops at ID 318 while French runs to 999. Every path sends the same list of allowed methods, including POST and PUT, even where those methods fail.

One error code hides two different mistakes

This session sent GET https://v2.jokeapi.dev/joke/Nope. It returned HTTP 400 with code: 106 and message: "No matching joke found."

This session then sent GET https://v2.jokeapi.dev/joke/Any?idRange=999999. It returned the same HTTP 400, the same code 106, and the same message.

The two requests fail for unrelated reasons. The first names a category that does not exist. The second names a valid category but asks for a joke ID past the highest one stored. Only the additionalInfo field tells them apart. The first reads "The specified category/ies is/are invalid." The second reads "The specified ID range is invalid. Got: "999999" but max possible ID range is: "0-318"." A caller that checks only code or message cannot tell a typo from an out-of-range request.

1,368 jokes, but English and French don't share a range

This session queried GET https://v2.jokeapi.dev/info. It reported jokes.totalCount: 1368 and a per-language idRange: en 0-318, fr 0-999, de 0-35, es 0-6, cs 0-3, pt 0-1.

Those six ranges add up to exactly 1,368 jokes. So the API has no single shared numbering scheme. Each language keeps its own ID sequence. French has 1,000 IDs, about three times the 319 that English has.

The idRange from an English call does not fit the other languages. It under-counts French by 681 IDs. It also covers IDs that do not exist in German, Spanish, Czech, or Portuguese.

One method list for every path, including the read-only ones

This session sent OPTIONS to /joke/Any, /info, and /categories. Each returned HTTP 200 with allow: GET, POST, HEAD, OPTIONS, PUT. The access-control-allow-methods header carried the same list.

The list does not match what each path accepts. This session sent POST and PUT to /joke/Any. Both returned HTTP 400 with an HTML error page, not JSON.

The docs name a separate /submit endpoint for new jokes, with a ?dry-run parameter that checks a joke without saving it. This session sent PUT https://v2.jokeapi.dev/submit?dry-run with a sample joke. It returned HTTP 201 with message: "Dry Run complete! No errors were found." No joke was added.

So the whole API sends one method list on every path. A client cannot read allow on one path to learn what that path accepts.

JokeAPI, by the numbers

Rendered live from the atlas entry
AuthenticationNone required
HTTPSSupported
CORSEnabled
PricingFree
FormatsJSON, XML, YAML, Text
Rate limit

120 requests per 60s window, confirmed live via response headers (ratelimit-limit: 120, ratelimit-remaining, ratelimit-reset, retry-after: 60)

Key endpoints
  • GET/joke/{category}
  • GET/categories
  • GET/flags
  • GET/info
jokeshumorcontent-filteringmulti-formatkeyless

Sources

Facts checked Sep 2026