Skip to main content

Command Palette

Search for a command to run...

The Day Finding the API Wasn't the Solution

A deep dive into child APIs, hidden search architectures, dynamic validation, and browser-dependent workflows inside a modern Vue.js application.

Updated
6 min read
The Day Finding the API Wasn't the Solution

When I first opened the Chinese portal, I expected a fairly standard workflow.

Most government portals follow a familiar pattern:

Search

API Request

Results

Detail API

Find the search API.

Find the detail API.

Build the scraper.

Move on.

That assumption lasted about thirty minutes.

First Observation: The Site Felt Different

The first clue was the frontend itself.

The application was heavily dynamic.

Page transitions were fast.

Search results appeared without full page reloads.

Developer tools immediately showed evidence of a modern SPA architecture.

Initial inspection suggested:

Vue.js frontend

Dynamic rendering

Client-side routing

API-driven content loading

Nothing unusual so far.

Most modern applications look exactly like this.

The interesting part came when searches were executed.

Watching the Network Tab

I began by monitoring every request generated during a search.

My expectation was simple:

User Search

Search API

Result List

I expected to see a request containing:

keyword=aspirin

or

searchTerm=aspirin

or something similar.

Instead, the request chain looked far more fragmented.

Multiple requests appeared.

Several configuration endpoints loaded.

Metadata requests loaded.

Dictionary lookups loaded.

Reference data loaded.

Then finally some APIs started returning actual product information.

False Victory #1

At this point I thought I had already found the solution.

One endpoint returned:

Product Name

Registration Number

Manufacturer

Approval Information

Everything looked perfect.

I copied the request.

Replayed it.

It worked.

At least initially.

I remember thinking:

Nice. This project will be finished quickly.

Then I looked closer.

The endpoint required an identifier.

Something like:

id=123456789

The endpoint itself wasn't generating data.

It was only consuming identifiers.

The question became:

Where does the identifier come from?

Understanding Child APIs

The endpoint was actually a child API.

Its responsibility was simple:

Identifier

Detailed Record

This explained why it looked so useful.

The portal already knew which record the user wanted.

The API simply returned details.

The problem was that I didn't know how to obtain millions of identifiers.

Without identifiers:

No Identifier

No Child API

The investigation shifted completely.

The objective was no longer finding APIs.

The objective became finding the source of identifiers.

Hypothesis #1: Hidden Search Endpoint

My first assumption was straightforward.

Surely there must be a search API somewhere.

Something like:

keyword

search endpoint

identifier list

So I began filtering requests.

Search.

Keyword.

Page.

List.

Query.

Product.

Drug.

Registration.

Everything that looked remotely relevant.

Nothing obvious appeared.

That was unusual.

Almost every application exposes the search request somewhere.

This one didn't.

The Rabbit Hole Begins

The deeper I looked, the stranger the architecture became.

Several possibilities emerged.

Possibility 1

The search request was encrypted.

Possibility 2

The search request was generated dynamically.

Possibility 3

The search request occurred through WebSocket communication.

Possibility 4

The search request occurred through internal browser logic before being transformed.

Possibility 5

The search architecture was split across multiple requests.

At this stage I had more questions than answers.

Replay Testing

Whenever I find an endpoint, I always test whether it can be replayed independently.

The process is simple.

Capture request.

Copy request.

Replay request.

Observe behavior.

Several endpoints failed this test.

Instead of JSON responses I received:

Empty responses

Validation errors

Login pages

Generic error messages

The endpoint clearly existed.

The endpoint clearly worked inside the browser.

The endpoint clearly failed outside the browser.

That contradiction became the next clue.

Dynamic Values Everywhere

I started comparing successful requests.

Certain fields continuously changed.

Examples included:

timestamp

nonce

signature

token

Every request appeared slightly different.

Even identical searches generated different values.

This suggested runtime generation.

The browser wasn't simply sending requests.

The browser was constructing requests.

Huge difference.

Session Dependency

The next experiment involved sessions.

I tested:

Fresh browser

Existing browser

New cookies

Old cookies

Different accounts

Expired sessions

Results suggested a strong dependency on browser state.

A request copied from one session frequently failed in another.

This meant:

Request

Session

Runtime Context

were all contributing factors.

Vue Bundle Investigation

Once network analysis stopped producing answers, I moved to frontend analysis.

This was probably the most frustrating phase.

Production Vue applications typically ship as:

chunk-vendor.js

app.js

runtime.js

Thousands of lines.

Minified.

Bundled.

Obfuscated.

Reading them feels like trying to reconstruct a machine from melted metal.

Still, clues existed.

Search-related functions appeared.

Request construction logic appeared.

Token generation appeared.

Validation functions appeared.

But the overall workflow remained fragmented.

Each answer generated three new questions.

The Signature Problem

One particular area consumed a surprising amount of time.

Signatures.

Several requests appeared to include generated validation values.

The challenge wasn't finding the signature.

The challenge was determining:

What generated it?

When was it generated?

Which parameters contributed?

Was it deterministic?

Was it session-bound?

Every failed replay pointed back toward this question.

When Reverse Engineering Stops Being API Discovery

This was the moment I realized the project had changed.

Initially I was performing API discovery.

Now I was performing architecture discovery.

Those are completely different activities.

API discovery asks:

What endpoint exists?

Architecture discovery asks:

Why does this endpoint exist?

Who calls it?

What generates its parameters?

What systems support it?

Much harder problem.

The Turning Point

Eventually I stopped trying to reproduce requests.

Instead I started reproducing behavior.

Rather than:

Replay Request

the new strategy became:

Open Browser

Perform Search

Capture Identifiers

Use Child APIs

The difference was subtle but enormous.

The browser already understood all hidden validation requirements.

Instead of fighting the application architecture, I began leveraging it.

That shift solved more problems than weeks of replay attempts.

Final Architecture Theory

After weeks of analysis, the architecture appeared closer to:

User Search

Vue Components

Frontend Validation

Runtime Parameter Generation

Internal Search Service

Identifier Generation

Search Results

Child APIs

Detailed Records

The child APIs were never the hard part.

The hidden identifier generation layer was.

What This Project Taught Me

The biggest lesson was surprisingly simple.

Finding an endpoint is easy.

Understanding a system is hard.

Modern applications increasingly hide critical business logic behind:

frontend frameworks

runtime validation

browser-generated parameters

session-aware security controls

The endpoint you see in DevTools is often only the final visible layer.

The real architecture frequently lives somewhere else.

And sometimes the most important API is the one you never manage to see.

O

That signature issue you ran into probably boils down to figuring out whether those parameters are cryptographically tied to your session or just derived from something predictable like a timestamp. That one detail makes a huge difference - it tells you whether cracking the signature is actually feasible or whether you're better off just spinning up browser automation and calling it a day. If you want to level up your architecture discovery game, start by explicitly mapping out where each parameter actually comes from like hardcoded stuff, session-derived, generated on the fly, whatever, right at the jump - that's honestly the difference between wrapping this up in a few hours versus drowning in it for weeks. This whole pattern is basically the industry standard now, especially in healthcare, fintech, and government systems where they're paranoid, rightfully so, about security

S

Appreciate!

The signature and session-validation aspect was definitely part of the investigation. What made this case particularly interesting was that multiple child APIs returning detailed records were already identifiable and functional once valid internal identifiers were available.

The bigger challenge was understanding the parent search architecture responsible for generating those identifiers in the first place. While the child APIs were visible through network traffic, the search workflow that produced the identifiers remained much harder to trace and isolate.

That's what made the exercise interesting from an API discovery perspective. The challenge wasn't only request validation, but also understanding how the search layer connected (href links) to the downstream record-level APIs.