Articles
HackerRank REST API Certification Prep: Pagination, Filtering, and Reliable Data Retrieval
Prepare for HackerRank REST API certification with an original pagination exercise, filter checks, empty-page cases, and deterministic result validation.
HackerRank REST API certification preparation should start with a simple promise: retrieve the complete dataset, apply the stated rule, and return the same correct result every time. A successful HTTP request proves that one response arrived. It does not prove that retrieval is complete. A solution can receive valid JSON and still miss qualifying records because it reads one page, stops on an empty page, or silently changes the filtering rule.
This guide builds those skills with an original three-page exercise.
Official facts below come from HackerRank and Python documentation checked on October 6, 2026. Preparation advice and the worked dataset are original exercises, not certification questions. Public employer-assessment anecdotes do not establish this certification's current question set or marking scheme.
What does the official certification tell you?
HackerRank's REST API Intermediate skills directory identifies consuming APIs and working with filtering, sorting, searching, and pagination. These are retrieval and data-processing competencies; preparing only general array algorithms leaves an obvious gap.
The certification landing page displayed 90 minutes and two questions when checked on October 6, 2026. Treat that as the public format observed on the check date, then read your actual instructions before starting. It does not reveal the questions you will receive or justify a prediction about passing thresholds. The certification introduction describes skills verification rather than a particular employer's recruitment process.
We did not establish two independent, same-cycle firsthand reports for this exact certification. Consequently, this article avoids alleged repeated questions, universal language restrictions, retry schedules, and score-to-interview promises. A company OA hosted on HackerRank can include REST work without being the public REST API certification.
Focus preparation on observable competence: explain the response contract, implement complete traversal, test boundary cases, and produce deterministic output.
Define the contract before making requests
Our mock endpoint is /datasets. Its query accepts lab and page. Every successful response contains an integer page, an integer total_pages, and a list named data. The dataset remains unchanged throughout one retrieval run.
The task is to return IDs for approved datasets belonging to A&B Lab with quality at least 90. Sort qualifying records by quality descending, then ID ascending. Quality must be a finite number; null, missing, Boolean, and nonnumeric values are excluded. Approval must be the Boolean true, rather than a truthy string. Dataset IDs are unique in this exercise.
Those details create an executable contract. “Find good datasets” would leave too many choices open: whether 90 qualifies, whether missing quality means zero, whether other laboratories should be accepted, and how ties should behave. Resolve such ambiguities from the problem statement rather than making convenient guesses.
Here is the complete fixture. The mock deliberately contains an unrelated-lab record so the client must enforce the final selection predicate.
| Page | Records returned | What should survive? |
|---|---|---|
| 1 of 3 | D01: quality 88, approved; D02: quality 91, unapproved; both target lab | Neither record |
| 2 of 3 | Empty data list | Nothing, but traversal continues |
| 3 of 3 | D03: quality 96, approved; D04: null quality; D05: quality 99, different lab; D06: quality 96, approved | D03 and D06 |
After all three pages are retrieved, the expected answer is ["D03", "D06"]. D05 must not win simply because its quality is highest. D03 precedes D06 because the tie rule uses ascending ID.
Why can an empty page still require another request?
An empty result array describes that page's contents. It does not override the envelope's traversal contract. In this fixture, page 2 says total_pages=3, so stopping there loses both qualifying records.
A first-page-only solution returns an empty answer. A loop that terminates whenever data is empty also returns an empty answer. Both implementations look reasonable if tested only against single-page examples. The three-page fixture distinguishes successful transport from complete retrieval.
Use the first envelope to establish the page count, then request pages 2 through that count. Validate that each response identifies the requested page and preserves the page count. For this mock, zero pages is represented by a first response with page=1, total_pages=0, and empty data.
That representation is an exercise choice, not a rule for every REST API. A different endpoint may use cursors, a next URL, or different numbering. Read its contract and adapt the traversal condition. Do not copy a loop mechanically across formats.
Separate retrieval from selection
Separate responsibilities so a failure points to retrieval, selection, or ordering. The retrieval function receives fetch(page), validates each envelope, and yields records. The selection function applies the lab, approval, and quality conditions, then sorts the survivors.
Here is the core of the original exercise. The HTTP adapter and stricter envelope checks sit outside this short selection example.
import math
def eligible_ids(records, lab, threshold):
selected = []
for row in records:
quality = row.get("quality")
if row.get("lab") != lab or row.get("approved") is not True:
continue
if isinstance(quality, bool) or not isinstance(quality, (int, float)):
continue
if not math.isfinite(quality) or quality < threshold:
continue
selected.append(row)
selected.sort(key=lambda row: (-row["quality"], row["id"]))
return [row["id"] for row in selected]
Notice that threshold comparison is inclusive: 90 qualifies. The Boolean check matters because Python treats bool as an integer subclass. The explicit finite-number rule excludes a value that could otherwise make numeric comparison or ordering unreliable.
Do not deduplicate by ID unless the prompt authorizes a duplicate policy. Our contract says IDs are unique. If a real exercise permits repeated IDs, clarify whether identical copies collapse, the latest version wins, or duplicates constitute an error. Each choice can change the answer.
For N retrieved records and K eligible records, selection takes O(N) scanning plus O(K log K) sorting, with O(K) retained records. A streaming implementation can avoid storing rejected rows. It still needs every page unless the endpoint contract proves that some requests can be skipped.
Encode parameters and handle transport failures explicitly
The lab name contains an ampersand. Manually constructing ?lab=A&B Lab&page=1 can split the query incorrectly. Use a query encoder, then verify that the server receives the original lab string. Python's urllib.parse documentation documents urlencode for producing query strings.
For the local HTTP fixture, the adapter builds the query with urlencode, calls urlopen with an explicit timeout, reads the response, and decodes JSON. The urllib.request documentation describes the HTTP interface and its error behavior. Keep network errors distinct from valid empty responses.
An HTTP failure, invalid JSON document, or malformed envelope should not be converted into [] and reported as a successful answer. That makes a missing page indistinguishable from a legitimate page with no matches.
For this exercise, these failures abort retrieval. Retrying a transient read may be reasonable in a production client, but that introduces a separate policy: which errors qualify, how many attempts are allowed, and whether the dataset remains stable. An assessment solution should satisfy the stated contract before adding unspecified retry machinery.
Likewise, a timeout value does not automatically create a complete end-to-end deadline. If the environment specifies an overall time budget, account for all requests and processing. Do not assume that a per-call setting bounds an arbitrarily long sequence of pages.
Use a failure matrix that challenges your assumptions
Our accompanying localhost fixture exercises actual HTTP requests and query decoding. Its successful run requests pages 1, 2, and 3 and produces D03 followed by D06. This verifies the original client against our mock server, not against HackerRank's grader.
| Probe | Expected outcome | Mistake it detects |
|---|---|---|
| Empty page 2, with three total pages | Continue to page 3 | Stopping on empty data |
| Quality exactly 90 | Include if other conditions hold | Accidental strict inequality |
| Null, missing, or Boolean quality | Exclude under this contract | Implicit coercion |
| Equal quality for D03 and D06 | Ascending ID tie order | Sorting only by quality |
Lab A&B Lab | Server receives the complete value | Manual query concatenation |
| Envelope says the wrong page | Raise a retrieval error | Accepting an unrelated response |
| HTTP 500 or invalid JSON | Fail visibly | Reporting partial retrieval as complete |
Add a zero-page case and an all-rejected case. They both yield an empty final answer, but their traces differ. One contains no records; the other successfully retrieves records that do not qualify. A useful explanation distinguishes those paths.
When a test fails, inspect the earliest broken promise. Were the requested parameters wrong? Was a page skipped? Did a record fail the predicate incorrectly? Did the final order differ? When the clock is running, use that first broken promise to choose your next check.
Keep the implementation proportional to the task
For this fixture, there are three requests and six records. A complicated concurrency layer adds little value and makes the trace harder to inspect. Sequential requests let you identify the failed page without coordinating partially completed workers. That is an exercise-specific design choice, not a general claim that parallel retrieval is always wrong.
If the prompt changes to a large number of pages, discuss request limits and memory before optimizing. Retain only eligible records when the output needs a sorted subset. If the output needs a single count, update an accumulator instead of keeping every record. If it needs the best ten results, a bounded ranking structure may be appropriate, but you still need the full retrieval contract.
Before returning the final answer, distinguish a validated empty result from an interrupted run. An empty list after all declared pages is evidence of no qualifying records under the stated predicate. An empty list after the first failed request is evidence of a broken client. Keeping those states separate is a small design decision with a large effect on correctness.
How should you explain the solution under time pressure?
A clear walkthrough can follow one qualifying record. D03 exists only on page 3. The client reaches it because traversal follows total_pages, accepts it because lab, approval, and quality all match, and places it before D06 because of the tie rule.
Then explain a rejection. D05 has the highest quality but belongs to another lab. A response can therefore contain impressive-looking values that the output must exclude. This demonstrates that your predicate comes from the task rather than from a convenient ranking shortcut.
Finally, state a limitation. Our fixture assumes a stable dataset. With offset pagination over changing data, records can move between pages during retrieval. A production system may need a snapshot or a cursor contract; sorting the final list cannot recover a record that was never fetched.
This is preparation advice, not a claim about an official speaking requirement. Practicing the explanation helps you discover assumptions even when the actual assessment accepts only code and output.