One POST per activity type. Send your content as JSON, get back an activity in your Puzzel.org account and a URL you can hand to players or drop into an iframe.
Base URL
https://puzzel.org/api/public/v1
Auth
Key + email in the body
Endpoints
20 activity types
Quota
10 activities a day
Your first request
Nothing to install and no handshake: post a JSON body with your key, your email and your content. The response carries the new activity's key and the URL it plays at.
POST crossword
curl -X POST https://puzzel.org/api/public/v1/crossword \
-H "Content-Type: application/json" \
-d '{
"account_api_key": "YOUR_API_KEY",
"email": "you@example.com",
"title": "Crossword",
"language": "en",
"items": [
{
"answer": "BANANA",
"description": "A long yellow fruit",
"type": "text"
},
{
"answer": "CHERRY",
"description": "A small red stone fruit",
"type": "text"
},
{
"answer": "MELON",
"description": "Big, green outside, sweet inside",
"type": "text"
}
]
}'
Every example on this page is a complete, runnable request. Swap in your own key and content and it works as-is.
Authentication
There are no headers and no bearer token. Both credentials travel in the JSON body of every request, and the key is only accepted for the account that email belongs to.
Field
Type
What it does
account_api_key
required
string
string
Your account's API key. It goes in the body, not in a header.
email
required
string
string
The address your Puzzel.org account signs in with. The key is only valid together with it.
Your key sits on the account section of your dashboard, behind Show.
Treat the key like a password. It creates and overwrites activities in your account, so keep it server-side and out of anything a browser can read.
The request body
Every endpoint takes the same five fields. What differs is the content field underneath them: most take an array of items, a few take one sentence or one image, and sudoku takes nothing at all.
Field
Type
What it does
account_api_key
required
string
string
Your account's API key. It goes in the body, not in a header.
email
required
string
string
The address your Puzzel.org account signs in with. The key is only valid together with it.
title
optional
string
string
The name the activity gets in your dashboard. Leave it out and the endpoint uses its own fallback name.
language
optional
string
string
Only decides the locale in the URL you get back — it does not translate anything you send. Word search also reads it to switch its filler letters to Arabic when it is "ar".
Default: "en"
activity_key
optional
string
string
Leave it out to create a new activity. Pass the key of one you already own and that activity is rebuilt instead.
settings is an object of per-endpoint options. Which ones an endpoint reads is listed with it below; anything else you put there is ignored.
What comes back
A successful call answers 200 with the new activity's key and the URL it plays at. Anything else answers with success set to false and a single error string.
{
"success": false,
"error": "Invalid Email or API Key"
}
The url you get back is the embed view. Swap embed for play to open it full-page, or for build to open it in the builder — the key after p= stays the same.
Creating vs. updating
Send activity_key and the activity behind it is rebuilt in place: its content is replaced, its name and version stamp are refreshed, and the key itself stays the same — so links and embeds you already shared keep working. Results, folder placement and every setting the endpoint does not write itself are left as they were.
activity_key
{
"account_api_key": "YOUR_API_KEY",
"email": "you@example.com",
"activity_key": "-Nq8sample_activity_key",
"title": "Fruit crossword, week 2",
"items": [
{
"answer": "BANANA",
"description": "A long yellow fruit",
"type": "text"
},
{
"answer": "CHERRY",
"description": "A small red stone fruit",
"type": "text"
},
{
"answer": "MELON",
"description": "Big, green outside, sweet inside",
"type": "text"
}
]
}
title is applied on every update, its default included — leave it out and the activity is renamed to that endpoint's fallback name.
The setting blocks an endpoint writes itself are rewritten from scratch, so an update also resets those to the values you send, or to the endpoint's defaults.
You can only update activities your own account owns. Someone else's key answers 403.
An update costs the same as a create: one call off today's quota.
Rate limit
10
10 activities per account per day
Every successful call counts, creates and updates alike. Go over and the next request answers 429 until the counter is cleared.
The counter is wiped once a day by a scheduled job, not on a rolling 24-hour window.
Errors
Errors always arrive as JSON with the same two fields, never as an HTML page. The error string is written to be read by a person — it names the field or the limit that failed.
Status
What it means
400
Bad Request
Something in the body is missing, malformed or out of range. The message names the field.
401
Unauthorized
The email is unknown, or the key does not belong to that account.
403
Forbidden
The activity_key you sent belongs to a different account.
429
Too Many Requests
Today's quota is used up. It clears once a day.
500
Server Error
The generator could not build a puzzle from what you sent — usually too few words, or words that cannot be fitted together.
Endpoints
One path per activity type, all POST, all under the same base URL. Each one lists the content it needs, the settings it reads and a request you can run.
Words & letters
F
I
G
A
T
R
I
P
M
Crossword puzzle
Interlocks your answers into a grid and numbers the clues for you.
POST/api/public/v1/typing-practiceAt least 1 in items
Content
api_c_typing_practice
Falls back to the name “Typing Practice API”
Example request
POST typing-practice
curl -X POST https://puzzel.org/api/public/v1/typing-practice \
-H "Content-Type: application/json" \
-d '{
"account_api_key": "YOUR_API_KEY",
"email": "you@example.com",
"title": "Typing Practice",
"language": "en",
"items": [
{
"answer": "The quick brown fox jumps over the lazy dog",
"description": "Every letter of the alphabet",
"type": "text"
},
{
"answer": "Pack my box with five dozen liquor jugs",
"description": "Another pangram",
"type": "text"
}
]
}'
Success
{
"success": true,
"id": "-Nq8sample_activity_key",
"url": "https://puzzel.org/en/typing-practice/embed?p=-Nq8sample_activity_key",
"message": "Typing Practice created successfully"
}
An array of pairs. Each pair holds the two cards that belong together.
Falls back to the name “Memory Game API”
Worth knowing
A card is an object with a type and a value. Use "text" for words, or "image", "audio", "youtube" or "link" with a URL in value, and add alt for a description.
POST/api/public/v1/matching-pairsAt least 2 in items
Content
api_c_matching_pairs
Falls back to the name “Matching Game API”
Worth knowing
A card is an object with a type and a value. Use "text" for words, or "image", "audio", "youtube" or "link" with a URL in value, and add alt for a description.
The endpoint stores as many cards as you send, so send exactly two per entry — front, then back.
A card is an object with a type and a value. Use "text" for words, or "image", "audio", "youtube" or "link" with a URL in value, and add alt for a description.
An array of categories, each with a name and the cards that belong in it.
Falls back to the name “Categorize Game API”
Worth knowing
A category sent without a name is saved as “Untitled Category”, so always send one.
A card is an object with a type and a value. Use "text" for words, or "image", "audio", "youtube" or "link" with a URL in value, and add alt for a description.
An array of sequences. Each holds its cards in the correct order.
Falls back to the name “Reorder Game API”
Worth knowing
The order you send is stored as the correct order — number one first.
A card is an object with a type and a value. Use "text" for words, or "image", "audio", "youtube" or "link" with a URL in value, and add alt for a description.
An array of questions. Multiple-choice questions carry their answers; open questions carry the answer you accept.
Falls back to the name “Quiz API”
Worth knowing
question_type is either "multiple_choice", where the right option carries isCorrect true, or "open_answer", which uses correct_answer instead. Left out, it is treated as multiple choice.
The quiz endpoint passes settings straight through as activity setting blocks, so it is not a place for loose options — adjust the quiz in the builder afterwards.
Example request
POST quiz
curl -X POST https://puzzel.org/api/public/v1/quiz \
-H "Content-Type: application/json" \
-d '{
"account_api_key": "YOUR_API_KEY",
"email": "you@example.com",
"title": "Quiz",
"language": "en",
"items": [
{
"question_type": "multiple_choice",
"description": "Which fruit is yellow?",
"answers": [
{
"type": "text",
"description": "Banana",
"isCorrect": true
},
{
"type": "text",
"description": "Cherry",
"isCorrect": false
}
]
},
{
"question_type": "open_answer",
"description": "What colour is a lemon?",
"correct_answer": "Yellow",
"explanation": "Lemons ripen from green to yellow."
}
]
}'
question_type is either "multiple_choice", where the right option carries isCorrect true, or "open_answer", which uses correct_answer instead. Left out, it is treated as multiple choice.
Settings it reads
Field
Type
What it does
number_of_tiles
optionalin settings
number
number
How many tiles the board has. Between 10 and 75.
Default: 30
game_mode
optionalin settings
string
string
Whether players race to the finish or collect items along the way.
One ofrace_to_finishcollect_items
Default: "race_to_finish"
Example request
POST board-game
curl -X POST https://puzzel.org/api/public/v1/board-game \
-H "Content-Type: application/json" \
-d '{
"account_api_key": "YOUR_API_KEY",
"email": "you@example.com",
"title": "Board Game",
"language": "en",
"items": [
{
"question_type": "multiple_choice",
"description": "Which fruit is yellow?",
"answers": [
{
"type": "text",
"description": "Banana",
"isCorrect": true
},
{
"type": "text",
"description": "Cherry",
"isCorrect": false
}
]
},
{
"question_type": "open_answer",
"description": "What colour is a lemon?",
"correct_answer": "Yellow",
"explanation": "Lemons ripen from green to yellow."
}
],
"settings": {
"number_of_tiles": 30,
"game_mode": "race_to_finish"
}
}'
Success
{
"success": true,
"id": "-Nq8sample_activity_key",
"url": "https://puzzel.org/en/board-game/embed?p=-Nq8sample_activity_key",
"message": "Board Game created successfully"
}
Nothing. The whole puzzle comes out of its two settings.
Falls back to the name “Sudoku API”
Worth knowing
Send no items and no sentence — size and difficulty are the entire input.
The builder only offers the difficulty for 2x3, 3x3 and 3x4. The API applies it to every size, 2x2 and 4x4 included.
Settings it reads
Field
Type
What it does
size
optionalin settings
string
string
The size of one block, written as rows by columns — 3x3 gives the classic 9x9 grid. The endpoint only checks that it parses as two numbers, so stay with the sizes the builder offers.
One of2x22x33x33x44x4
Default: "3x3"
difficulty_level
optionalin settings
string
string
How many numbers are left on the board to start from.