Support this site by joining our Patreon. For as little as $1 a month you receive exclusive ad-free content, ebooks and online training courses. - Learn more
API Challenges Progress
Getting Started
Use the Descriptions of the challenges below to explore the API and solve the challenges. Remember to use the API documentation to see the format of POST requests.
Progress, and the TODOs database content can be saved to, and restored from, LocalStorage in the browser - or managed via the API.
Unknown Challenger ID
To view your challenges status in multi-user mode, make sure you have registered as a challenger using a `POST` request to `/challenger` and are including an `X-CHALLENGER` header in all your requests.
Then view the challenges in the GUI by visiting `/gui/challenges/{GUID}`, where `{GUID}` is the value in the `X-CHALLENGER` header.
Challenger sessions are purged from the server memory after 10 minutes of inactivity.
Challenger progress is configured to save on the server after 10 challenges are completed.To restore a previously saved session progress from the server, issue an API request with the X-CHALLENGER header (note this will restore the completion state of challenges, but not the data you were using).
Session state and current todo list can be stored to local storage, and later restored using the GUI buttons or via API.
You can find more information about this on the Multi User Help Page
Challenge Sections
- Getting Started
- First Real Challenge
- GET Challenges
- GET Filter Challenges
- GET Sorted Challenges
- GET Pagination Challenges
- HEAD Challenges
- Creation Challenges with POST
- Creation Challenges with PUT
- Update Challenges with POST
- Update Challenges with PUT
- DELETE Challenges
- QUERY Challenges
- PATCH Challenges
- OPTIONS Challenges
- Accept Challenges
- Content-Type Challenges
- Content-Disposition Challenges
- Fancy a Break? Restore your session
- Mix Accept and Content-Type Challenges
- Status Code Challenges
- HTTP Method Override Challenges
- Authentication Challenges
- Authorization Challenges
- Miscellaneous Challenges
Getting Started
If you want to track your challenge progress, in multi-user mode then you need to solve the challenges in this section to generate a unique ID that we can associate your progress with.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 01 | POST /challenger (201) | false | Issue a POST request on the `/challenger` end point, with no body, to create a new challenger session. Use the generated X-CHALLENGER header in future requests to track challenge completion. Hints
Solve NowSolution
|
First Real Challenge
For your first challenge, get the list of challenges. You'll be able to use this to see your progress in your API Client, as well as using the GUI.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 02 | GET /challenges (200) | false | Issue a GET request on the `/challenges` end point Hints
Solve Now |
GET Challenges
To retrieve, or read information from an API we issue GET requests. This section has a bunch of GET request challenges to try out.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 03 | GET /todos (200) | false | Issue a GET request on the `/todos` end point Hints
Solve Now |
| 04 | GET /todo (404) not plural | false | Issue a GET request on the `/todo` end point should 404 because nouns should be plural Hints
Solve Now |
| 05 | GET /todos/{id} (200) | false | Issue a GET request on the `/todos/{id}` end point to return a specific todo Hints
Solve Now |
| 06 | GET /todos/{id} (404) | false | Issue a GET request on the `/todos/{id}` end point for a todo that does not exist Hints
Solve Now |
GET Filter Challenges
To retrieve, or read information from an API we issue GET requests and we can control the results using query parameters. This section has a bunch of GET request challenges to try out filtering.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 07 | GET /todos (200) ?filter | false | Issue a GET request on the `/todos` end point with a query filter to get only todos which are 'done'. There must exist both 'done' and 'not done' todos, to pass this challenge. Hints
Solve Now |
| 08 | GET /todos (200) ?filter id greater than | false | Issue a GET request on the `/todos` end point with an id filter to return todos with an id greater than a supplied value. Hints
Solve NowSolution |
| 09 | GET /todos (200) ?filter id less than | false | Issue a GET request on the `/todos` end point with an id filter to return todos with an id less than a supplied value. Hints
Solve NowSolution |
| 10 | GET /todos (200) ?filter id single result | false | Issue a GET request on the `/todos` end point with an id filter that returns one todo while multiple todos exist in the database. Hints
Solve NowSolution |
| 11 | GET /todos (200) ?filter description regex | false | Issue a GET request on the `/todos` end point with a regular expression filter on description that returns todos with non-empty descriptions. Hints
Solve NowSolution |
| 12 | GET /todos (200) ?filter description wildcard | false | Issue a GET request on the `/todos` end point with a wildcard filter on description that returns todos with non-empty descriptions. Hints
Solve NowSolution |
GET Sorted Challenges
To retrieve, or read information from an API we issue GET requests and we can sort the results using query parameters. This section has a bunch of GET request challenges to try out sorting.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 13 | GET /todos (200) ?_sortBy ascending | false | Issue a GET request on the `/todos` end point with a query parameter to sort todos ascending by a field. Hints
Solve NowSolution |
| 14 | GET /todos (200) ?_sortBy descending | false | Issue a GET request on the `/todos` end point with a query parameter to sort todos descending by a field. Hints
Solve NowSolution |
| 15 | GET /todos (200) ?_sortBy multiple | false | Issue a GET request on the `/todos` end point with a query parameter to sort todos by multiple fields. Hints
Solve NowSolution |
| 16 | GET /todos (200) ?filter&_sortBy | false | Issue a GET request on the `/todos` end point with a query filter and a query parameter to sort the filtered todos. Hints
Solve NowSolution |
GET Pagination Challenges
Pagination lets us retrieve a collection in smaller pages using limit and offset query parameters. These challenges use GET requests to practise paging by itself, and with filtering and sorting.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 17 | GET /todos (200) ?_limit | false | Issue a GET request on the `/todos` end point with a query parameter to limit the returned todos to 8 items. Hints
Solve NowSolution |
| 18 | GET /todos (200) ?_limit&_offset | false | Issue a GET request on the `/todos` end point with query parameters to limit the returned todos to 5 items starting from offset 5. Hints
Solve NowSolution |
| 19 | GET /todos (400) ?_limit too high | false | Issue a GET request on the `/todos` end point with a pagination limit above the configured maximum to receive a 400 status code. Hints
Solve NowSolution |
| 20 | GET /todos (200) ?_sortBy&_limit&_offset | false | Issue a GET request on the `/todos` end point with query parameters to sort todos by id descending, then return a page of 5 todos from offset 5. Hints
Solve NowSolution |
| 21 | GET /todos (200) ?filter&_limit&_offset | false | Issue a GET request on the `/todos` end point with query parameters to filter todos with doneStatus=false, then return a page of 2 todos from offset 1. Hints
Solve NowSolution |
HEAD Challenges
A HEAD request, is like a GET request, but only returns the headers and status code.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 22 | HEAD /todos (200) | false | Issue a HEAD request on the `/todos` end point Hints
Solve Now |
Creation Challenges with POST
A POST request can be used to create and update data, these challenges are to 'create' data.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 23 | POST /todos (201) | false | Issue a POST request to successfully create a todo Hints
Solve Now |
| 24 | POST /todos (422) doneStatus | false | Issue a POST request to create a todo but fail validation on the `doneStatus` field Hints
Solve NowSolution
|
| 25 | POST /todos (422) title too long | false | Issue a POST request to create a todo but fail length validation on the `title` field because your title exceeds maximum allowable characters. Hints
Solve NowSolution
|
| 26 | POST /todos (422) description too long | false | Issue a POST request to create a todo but fail length validation on the `description` because your description exceeds maximum allowable characters. Hints
Solve NowSolution
|
| 27 | POST /todos (201) max out content | false | Issue a POST request to create a todo with maximum length title and description fields. Hints
Solve NowSolution
|
| 28 | POST /todos (413) content too long | false | Issue a POST request to create a todo but fail payload length validation on the `description` because your whole payload exceeds maximum allowable 5000 characters. Hints
Solve NowSolution
|
| 29 | POST /todos (422) extra | false | Issue a POST request to create a todo but fail validation because your payload contains an unrecognised field. Hints
Solve NowSolution
|
Creation Challenges with PUT
A PUT request can often used to create and update data. The todo application we are using has automatically generated ids, so you cannot use PUT to create.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 30 | PUT /todos/{id} (422) | false | Issue a PUT request to unsuccessfully create a todo Hints
Solve NowSolution
|
Update Challenges with POST
Use a POST request to amend something that already exists. These are 'partial' content updates so you usually don't need to have all details of the entity in the request, e.g. you could just update a title, or a description, or a status
| ID | Challenge | Done | Description |
|---|---|---|---|
| 31 | POST /todos/{id} (200) | false | Issue a POST request to successfully update a todo Hints
Solve Now |
| 32 | POST /todos/{id} (404) | false | Issue a POST request for a todo which does not exist. Expect to receive a 404 response. Hints
Solve NowSolution
|
Update Challenges with PUT
A PUT request can be used to amend data. REST Put requests are idempotent, they provide the same result each time.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 33 | PUT /todos/{id} full (200) | false | Issue a PUT request to update an existing todo with a complete payload i.e. title, description and donestatus. Hints
Solve NowSolution
|
| 34 | PUT /todos/{id} partial (200) | false | Issue a PUT request to update an existing todo with just mandatory items in payload i.e. title. Hints
Solve NowSolution
|
| 35 | PUT /todos body id (200) | false | Issue a PUT request to update an existing todo using an id in the payload. Hints
Solve NowSolution
|
| 36 | PUT /todos/{id} no body id (200) | false | Issue a PUT request to update an existing todo using the URL id and no id in the payload. Hints
Solve NowSolution
|
| 37 | PUT /todos/{id} no title (422) | false | Issue a PUT request to fail to update an existing todo because title is missing in payload. Hints
Solve NowSolution
|
| 38 | PUT /todos no id (422) | false | Issue a PUT request to fail to update a todo because no id is provided in the URL or payload. Hints
Solve NowSolution
|
| 39 | PUT /todos/{id} not found (404) | false | Issue a PUT request to fail to update a todo because the URL id does not exist. Hints
Solve NowSolution
|
| 40 | PUT /todos/{id} no amend id (422) | false | Issue a PUT request to fail to update an existing todo because id different in payload. Hints
Solve NowSolution
|
DELETE Challenges
Use a DELETE request to delete an entity. Since this is an extreme request, normally you have to be logged in or authenticated, but we wanted to make life easier for you so we cover authentication later. Anyone can delete To Do items without authentication in this system.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 41 | DELETE /todos/{id} (204) | false | Issue a DELETE request to successfully delete a todo Hints
Solve NowSolution |
QUERY Challenges
A QUERY request is a safe read request which allows query content in the request body.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 42 | QUERY /todos (200) | false | Issue a QUERY request on the `/todos` end point with form-encoded query content to get only todos which are 'done'. There must exist both 'done' and 'not done' todos, to pass this challenge. Hints
Solve NowSolution |
PATCH Challenges
A PATCH request can be used to amend part of an existing entity. These challenges cover partial JSON updates, JSON Merge Patch, and JSON Patch.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 43 | PATCH /todos/{id} (200) partial | false | Issue a PATCH request to update an existing todo using a partial JSON payload. learn more about patch. Hints
Solve NowSolution |
| 44 | PATCH /todos/{id} (200) merge-patch | false | Issue a PATCH request to update an existing todo using JSON Merge Patch. learn more about patch. Hints
Solve NowSolution |
| 45 | PATCH /todos/{id} (200) json-patch | false | Issue a PATCH request to update an existing todo using JSON Patch operations. learn more about patch. Hints
Solve NowSolution |
OPTIONS Challenges
Use an OPTIONS verb and check the `Allow` header, this will show you what verbs are allowed to be used on an endpoint. When you test APIs it is worth checking to see if all the verbs listed are allowed or not.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 46 | OPTIONS /todos (200) | false | Issue an OPTIONS request on the `/todos` end point. You might want to manually check the 'Allow' header in the response is as expected. Hints
Solve Now |
Accept Challenges
The `Accept` header, tells the server what format you want the response to be in. By changing the `Accept` header you can specify JSON or XML.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 47 | GET /todos (200) XML | false | Issue a GET request on the `/todos` end point with an `Accept` header of `application/xml` to receive results in XML format Hints
Solve Now |
| 48 | GET /todos (200) JSON | false | Issue a GET request on the `/todos` end point with an `Accept` header of `application/json` to receive results in JSON format Hints
Solve Now |
| 49 | GET /todos (200) ANY | false | Issue a GET request on the `/todos` end point with an `Accept` header of `*/*` to receive results in default JSON format Hints
Solve Now |
| 50 | GET /todos (200) XML pref | false | Issue a GET request on the `/todos` end point with an `Accept` header of `application/xml, application/json` to receive results in the preferred XML format Hints
Solve Now |
| 51 | GET /todos (200) no accept | false | Issue a GET request on the `/todos` end point with no `Accept` header present in the message to receive results in default JSON format Hints
Solve Now |
| 52 | GET /todos (406) | false | Issue a GET request on the `/todos` end point with an `Accept` header `application/gzip` to receive 406 'NOT ACCEPTABLE' status code Hints
Solve Now |
| 53 | GET /todos/{id} (200) text/calendar | false | Issue a GET request on the `/todos/{id}` end point with an `Accept` header of `text/calendar` to receive the todo as a VTODO. Hints
Solve NowSolution |
Content-Type Challenges
The `Content-Type` header, tells the server what format type your 'body' content is, e.g. are you sending XML or JSON.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 54 | POST /todos XML | false | Issue a POST request on the `/todos` end point to create a todo using Content-Type `application/xml`, and Accepting only XML ie. Accept header of `application/xml` Hints
Solve Now |
| 55 | POST /todos JSON | false | Issue a POST request on the `/todos` end point to create a todo using Content-Type `application/json`, and Accepting only JSON ie. Accept header of `application/json` Hints
Solve Now |
| 56 | POST /todos (415) | false | Issue a POST request on the `/todos` end point with an unsupported content type to generate a 415 status code Hints
Solve Now |
Content-Disposition Challenges
The `Content-Disposition` header can tell a client to treat a response as a file download, and can suggest the filename to use.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 57 | GET /todos/export (200) CSV download | false | Issue a GET request on the `/todos/export?format=csv` end point and receive a CSV response with a `Content-Disposition` header for `todos.csv` Hints
Solve NowSolution |
| 58 | GET /todos/export (200) HTML download | false | Issue a GET request on the `/todos/export?format=html` end point and receive an HTML response with a `Content-Disposition` header for `todos.html` Hints
Solve NowSolution |
| 59 | GET /todos/export (200) tab-delimited download | false | Issue a GET request on the `/todos/export?format=tsv` end point and receive a tab-delimited response with a `Content-Disposition` header for `todos.tsv` Hints
Solve NowSolution |
Fancy a Break? Restore your session
Your challenge progress can be saved, and as long as you remember you challenger ID you can restore it. Leaving a challenger idle in the system for more than 10 minutes will remove the challenger from memory. Challenger status and the todos database can be saved to, and restored from, the browser localStorage.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 60 | GET /challenger/guid (200) | false | Issue a GET request on the `/challenger` end point with an existing challenger GUID to restore that challenger's progress into memory. Hints
Solve NowSolution
|
| 61 | POST /challenger (existing X-CHALLENGER) | false | Issue a POST request on the `/challenger` end point, with an existing challenger GUID as the X-CHALLENGER header to restore that challenger's progress into memory. Hints
Solve NowSolution
|
| 62 | GET /challenger/guid (existing X-CHALLENGER) | false | Issue a GET request on the `/challenger/{guid}` end point, with an existing challenger GUID. This will return the progress data payload that can be used to later restore your progress to this status. Hints
Solve NowSolution |
| 63 | PUT /challenger/guid RESTORE | false | Issue a PUT request on the `/challenger/{guid}` end point, with an existing challenger GUID to restore that challenger's progress into memory. Hints
Solve NowSolution
|
| 64 | PUT /challenger/guid (409) mismatch | false | Issue a PUT request on the `/challenger/{guid}` end point where the URL GUID does not match the payload X-CHALLENGER value. Hints
Solve NowSolution |
| 65 | PUT /challenger/guid CREATE | false | Issue a PUT request on the `/challenger/{guid}` end point, with a challenger GUID not currently in memory to restore that challenger's progress into memory. Hints
Solve NowSolution
|
| 66 | GET /challenger/database/guid (200) | false | Issue a GET request on the `/challenger/database/{guid}` end point, to retrieve the current todos database for the user. You can use this to restore state later. Hints
Solve NowSolution |
| 67 | PUT /challenger/database/guid (Update) | false | Issue a PUT request on the `/challenger/database/{guid}` end point, with a payload to restore the Todos database in memory. Hints
Solve NowSolution
|
Mix Accept and Content-Type Challenges
We can mix the `Accept` and `Content-Type` headers so that we can send JSON but receive XML. These challenges encourage you to explore some combinations.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 68 | POST /todos XML to JSON | false | Issue a POST request on the `/todos` end point to create a todo using Content-Type `application/xml` but Accept `application/json` Hints
Solve Now |
| 69 | POST /todos JSON to XML | false | Issue a POST request on the `/todos` end point to create a todo using Content-Type `application/json` but Accept `application/xml` Hints
Solve Now |
Status Code Challenges
Status-codes are essential to understand, so we created some challenges that help you trigger more status codes. Remember to review httpstatuses.com to learn what the status codes mean.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 70 | DELETE /heartbeat (405) | false | Issue a DELETE request on the `/heartbeat` end point and receive 405 (Method Not Allowed) Hints
Solve Now |
| 71 | PATCH /heartbeat (500) | false | Issue a PATCH request on the `/heartbeat` end point and receive 500 (internal server error) Hints
Solve Now |
| 72 | TRACE /heartbeat (501) | false | Issue a TRACE request on the `/heartbeat` end point and receive 501 (Not Implemented) Hints
Solve Now |
| 73 | GET /heartbeat (204) | false | Issue a GET request on the `/heartbeat` end point and receive 204 when server is running Hints
Solve Now |
| 74 | GET /heartbeat (431) X-CHALLENGER too long | false | Issue a GET request on the `/heartbeat` end point with an X-CHALLENGER header value that is too long and receive 431 (Request Header Fields Too Large). Hints
Solve NowSolution |
HTTP Method Override Challenges
Some HTTP Clients can not send all verbs e.g. PATCH, DELETE, PUT. Use an X-HTTP-Method-Override header to simulate these with a POST request
| ID | Challenge | Done | Description |
|---|---|---|---|
| 75 | POST /heartbeat as DELETE (405) | false | Issue a POST request on the `/heartbeat` end point and receive 405 when you override the Method Verb to a DELETE Hints
Solve NowSolution
|
| 76 | POST /heartbeat as PATCH (500) | false | Issue a POST request on the `/heartbeat` end point and receive 500 when you override the Method Verb to a PATCH Hints
Solve NowSolution
|
| 77 | POST /heartbeat as Trace (501) | false | Issue a POST request on the `/heartbeat` end point and receive 501 (Not Implemented) when you override the Method Verb to a TRACE Hints
Solve NowSolution
|
Authentication Challenges
Authentication is telling the system who you are. In multi-user mode you are already doing that with the X-CHALLENGER header, but we have added an extra level of security on the /secret section. So first Authenticate with Basic Authentication to find out the token to use for authorisation for later challenges.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 78 | POST /secret/token (401) | false | Issue a POST request on the `/secret/token` end point and receive 401 when Basic auth username/password is not admin/password Hints
Solve Now |
| 79 | POST /secret/token (201) | false | Issue a POST request on the `/secret/token` end point and receive 201 when Basic auth username/password is admin/password Hints
Solve Now |
Authorization Challenges
Once the system knows who you are, authorization is if you have the correct level of access. In these challenges the authorization is granted using a custom API header X-AUTH-TOKEN or using a Bearer Authorization header.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 80 | GET /secret/note (403) | false | Issue a GET request on the `/secret/note` end point and receive 403 when X-AUTH-TOKEN does not match a valid token Hints
Solve Now |
| 81 | GET /secret/note (401) | false | Issue a GET request on the `/secret/note` end point and receive 401 when no X-AUTH-TOKEN header present Hints
Solve Now |
| 82 | GET /secret/note (200) | false | Issue a GET request on the `/secret/note` end point receive 200 when valid X-AUTH-TOKEN used - response body should contain the note Hints
Solve Now |
| 83 | POST /secret/note (200) | false | Issue a POST request on the `/secret/note` end point with a note payload e.g. {"note":"my note"} and receive 200 when valid X-AUTH-TOKEN used. Note is maximum length 100 chars and will be truncated when stored. Hints
Solve Now |
| 84 | POST /secret/note (401) | false | Issue a POST request on the `/secret/note` end point with a note payload {"note":"my note"} and receive 401 when no X-AUTH-TOKEN present Hints
Solve Now |
| 85 | POST /secret/note (403) | false | Issue a POST request on the `/secret/note` end point with a note payload {"note":"my note"} and receive 403 when X-AUTH-TOKEN does not match a valid token Hints
Solve Now |
| 86 | GET /secret/note (Bearer) | false | Issue a GET request on the `/secret/note` end point receive 200 when using the X-AUTH-TOKEN value as an Authorization Bearer token - response body should contain the note Hints
Solve Now |
| 87 | POST /secret/note (Bearer) | false | Issue a POST request on the `/secret/note` end point with a note payload e.g. {"note":"my note"} and receive 200 when valid X-AUTH-TOKEN value used as an Authorization Bearer token. Status code 200 received. Note is maximum length 100 chars and will be truncated when stored. Hints
Solve Now |
Miscellaneous Challenges
We left these challenges to the end because they seemed fun, but... different.
| ID | Challenge | Done | Description |
|---|---|---|---|
| 88 | DELETE /todos/{id} (204) all | false | Issue a DELETE request to successfully delete the last todo in system so that there are no more todos in the system Hints
Solve NowSolution |
| 89 | POST /todos (409) max todos | false | Issue as many POST requests as it takes to exceed the maximum number of TODOS allowed for a user. The maximum number should be listed in the documentation. Hints
Solve NowSolution |
Support this site by joining our Patreon. For as little as $1 a month you receive exclusive ad-free content, ebooks and online training courses. - Learn more