API
TheJokeDB has a public JSON API. Single jokes, random picks and search need no key; the listing endpoints (/jokes and /tags/{type}/{slug}/jokes) need one, because they walk the whole catalogue. The machine-readable
description is at /v1/openapi.yaml under the base URL (/api/v1/openapi.yaml on this site), with the right server address filled in.
Basics
- Base URL:
https://api.thejokedb.com/v1(GET /on the API host lists the current version and the docs;/api/v1on this site reaches the same API). Every response is JSON, UTF-8, gzip when you ask for it. - Jokes are never translated.
langpicks the language a joke was written in and defaults to your request locale (the site language cookie, thenAccept-Language, then English). Tag names and error messages follow the same locale. - Lists are keyset paginated: pass
next_cursorback ascursor.limitis 1–50, default 10. - Jokes and tags are cacheable. Responses carry
Cache-Controland a weakETag; sendIf-None-Matchto get a304. - CORS is open: browsers may call the API from any origin.
Limits
Anonymous clients get 300 requests a minute per address, with a burst of 60.
Send an API key as Authorization: Bearer tjdb_… for ten times that and for
the write endpoints. Every response reports X-RateLimit-Limit and
X-RateLimit-Remaining; over the limit you get 429 with Retry-After.
Votes are limited separately to 60 a minute.
Endpoints
| Method | Path | What it does |
|---|---|---|
| GET | /jokes |
List jokes. Filters: lang, structure, max_rating, audience, tag=type:slug, sort=best|newest. Returns total. |
| GET | /jokes/random |
A random short joke. lang, max_rating. Never cached. |
| GET | /jokes/search?q= |
Substring search over setup and punchline, newest first. q is 2–100 characters. |
| GET | /jokes/{id} |
One joke with its tags. |
| GET | /jokes/{id}/vote |
The tally, the score and your own vote. |
| POST | /jokes/{id}/vote |
Cast or change your vote: {"vote": "funny"}, meh or not-funny. |
| DELETE | /jokes/{id}/vote |
Take your vote back. |
| GET | /tags |
Every user-facing tag; type=topic or tone to narrow. |
| GET | /tags/{type}/{slug} |
One tag. |
| GET | /tags/{type}/{slug}/jokes |
Jokes carrying a tag; same parameters as /jokes. |
| POST | /submissions |
Submit a joke for review. Needs a key with the submit scope. |
A joke
{
"id": "rhrwseq7bpt5u",
"setup": "I used to be a banker, but I lost interest.",
"punchline": null,
"structure": "one-liner",
"length": "one-liner",
"rating": "clean",
"audience": "general",
"lang": "en",
"score": 0.25,
"votes": { "funny": 1, "meh": 0, "not_funny": 0 },
"tags": [ { "type": "topic", "slug": "banks", "name": "Banks" } ],
"created_at": "2026-10-21T05:45:00Z"
}
punchline is null for single-part forms. rating is ordered
(clean < mild < crude < explicit), so max_rating=mild means clean
or mild. score is derived from votes:
(funny − not funny) ÷ (votes + 3), so one vote cannot outrank a well-voted
joke.
Voting
Votes are anonymous. The first vote sets a tjdb_voter cookie for a year;
only a hash of it is stored, never the value or your address. One vote per
joke per cookie; voting again replaces it.
curl -X POST https://thejokedb.com/api/v1/jokes/rhrwseq7bpt5u/vote \
-H 'Content-Type: application/json' -d '{"vote":"funny"}'
Submitting
curl -X POST https://thejokedb.com/api/v1/submissions \
-H 'Authorization: Bearer tjdb_…' -H 'Content-Type: application/json' \
-d '{"setup":"Why did the API cross the road?","punchline":"To GET to the other side.","lang":"en"}'
You get 202 and a submission id. The joke is published only after a
person has read and approved it. The same text (ignoring case and
punctuation) is accepted once; a repeat is 409.
Errors
Every error is {"code": …, "error": …} with an optional param naming
the offending parameter. Codes: invalid_param, invalid_cursor,
invalid_input, not_found, method_not_allowed, unauthorized,
forbidden, duplicate, rate_limited, internal. The error text is
localised and may change; the code will not.
Keys
Keys are issued by the site operator and look like tjdb_ followed by 38
characters. Scopes: read (the listing endpoints, for apps, bots and
integrations that walk the catalogue) and submit (submissions). Keep them
server-side; they are not meant for browser code. To ask for a key, or for
anything else about the API, write to [email protected].