How to Find API Dependencies Across a Codebase

An API dependency is more than an HTTP call. It includes the configuration that selects a provider, the client that sends requests, the code that interprets responses, and the workflow that depends on the result.

Searching for an endpoint is a useful starting point. It is not proof that you have found every consumer. Generated clients, shared wrappers, dynamically assembled URLs, and infrequently executed jobs can hide important connections.

The practical goal is a scoped dependency inventory: enough evidence to identify likely consumers, assign owners, and decide what to inspect next. Our earlier article on what happens when an API endpoint disappears explains the reliability consequences. Here, the focus is finding the code and workflows behind those consequences.

Start with an integration fingerprint

Before searching, collect identifiers that could appear in different layers:

  • Provider hostname and known aliases.
  • Endpoint paths, including older versions.
  • SDK package names and generated client classes.
  • Configuration keys for base URLs and credentials.
  • Operation names and distinctive response fields.

Use a fictional shipping integration as an example. A SaaS application calls ParcelBridge through api.parcelbridge.example, with a known endpoint of /v1/shipments. Its configuration uses PARCELBRIDGE_BASE_URL, and one response field is tracking_status.

Treat those identifiers as search inputs, not a complete specification. The same integration might appear as shippingClient inside application code and as an environment variable reference in deployment configuration.

Record your scope too: repositories, branches, services, and environments. “Searched the main application repository” is useful evidence. “Checked everything” usually conceals assumptions.

Search literal identifiers before broad patterns

Start with exact matches. They are easier to interpret than a broad search for every HTTP request:

rg -n -F \
  -e 'api.parcelbridge.example' \
  -e '/v1/shipments' \
  -e 'PARCELBRIDGE_BASE_URL' \
  -e 'tracking_status' .

Then search for request construction and client usage:

rg -n \
  -e 'fetch\(' \
  -e 'axios\.' \
  -e 'requests\.(get|post|put|patch|delete)\(' \
  -e 'shippingClient' \
  -g '*.{ts,tsx,js,py}' .

These patterns are starting points, not a universal HTTP detector. They miss aliases, other languages, wrappers, and alternative libraries. Adapt them to the codebase rather than treating a clean result as confirmation of absence.

In repository code search, run the same identifiers across relevant repositories. A query such as org:YOUR_ORG "PARCELBRIDGE_BASE_URL" can uncover consumers outside the application you started with; syntax depends on your search platform.

For each meaningful match, trace callers toward a business operation. A request helper is a technical dependency. A shipment refresh job is an operational dependency with an owner and a failure mode.

Inspect configuration, manifests, and generated clients

A hostname may never appear in application source. Look in environment templates, Helm values, Terraform, container definitions, and deployment scripts:

rg -n -i \
  -e 'parcelbridge' \
  -e 'shipping.*(url|host|endpoint)' \
  -g '*.yaml' -g '*.yml' -g '*.tf' \
  -g '*.json' -g '*.toml' -g '.env*' .

By default, ripgrep skips hidden and ignored files. If expected configuration is missing, inspect selected directories with --hidden or, when necessary, --no-ignore. Scope those searches carefully: ignored directories can contain dependencies, build output, or secrets. Do not paste credentials into an inventory or issue.

Check package manifests and lockfiles for SDKs. Follow the import into any generated client, then inspect its base URL configuration, operation methods, and generation inputs. Generated code may be excluded from ordinary searches, downloaded during a build, or distributed as a package.

Where an OpenAPI document exists, use it to connect server definitions, paths, operations, and schemas to client code. The OpenAPI Specification defines these structures. An operationId, when present, can be another search key, although generators may transform its spelling.

A specification describes an interface; it does not establish which operations your application actually uses. Likewise, installing an SDK does not prove an active dependency.

Follow dynamic URLs and indirect consumers

Literal search becomes weaker when URLs are assembled at runtime:

const resource = config.shipmentResource;
const url = `${config.apiBase}/${config.apiVersion}/${resource}`;
return http.get(url);

Searching for /v1/shipments will miss this request. Trace where each configuration value comes from, including deployment overrides and tenant-specific settings.

Other blind spots include:

  • An internal gateway that forwards requests to the provider.
  • A shared library that hides HTTP calls behind domain methods.
  • Queue workers triggered after the initial user request.
  • Scheduled tasks, administrative scripts, and migration utilities.
  • Webhook handlers that consume provider events rather than call endpoints.

In the fictional ParcelBridge application, the web service might enqueue a shipment ID while a worker makes the actual request. The dependency map should connect both components to the shipment-status workflow.

There is a tradeoff here: tracing every abstraction can become expensive. Begin with the integration and workflow under investigation, then expand when you find a shared client, gateway, or configuration source that suggests more consumers.

Add runtime evidence without overstating it

Static inspection identifies possible execution paths. Runtime evidence helps establish which paths executed in a particular environment and time window.

Useful sources include outbound request traces, application logs, gateway records, scheduled-job histories, and queue-consumer activity. Where instrumentation permits, connect the destination host and method to the calling service, route or job, and deployed version.

For ParcelBridge, a trace might show a worker calling the shipments endpoint during a scheduled refresh. That supports an observed dependency. It does not establish whether an administrative backfill uses the same endpoint once a month.

Record the observation window and limitations. Sampling, missing instrumentation, inactive tenants, and failed scheduling can all explain an absent call. “Not observed during this window” is more accurate than “unused.”

Avoid collecting authorization headers or full payloads merely to establish dependency edges. Destination metadata and relevant code locations may be sufficient; follow your team’s data-handling rules.

Build an inventory with owners and evidence

Keep the inventory small enough to maintain. A spreadsheet or repository document is sufficient if it captures actionable relationships.

For the fictional example, an entry could contain:

Field Example
Producer operation ParcelBridge GET /v1/shipments/{id}
Consumer Shipment refresh worker
Code location workers/refreshShipment.ts
Workflow Refresh customer-visible tracking status
Assumption Response contains a recognized tracking_status value
Owner Team responsible for shipment tracking
Evidence Static call path; runtime observation still pending
Open question Does the administrative backfill share this client?

Keep dependency evidence separate from failure evidence. Finding a consumer does not prove a provider change breaks it. That requires inspecting the changed assumption and running an appropriate check.

Assign ownership to the workflow, not just the shared client. Otherwise, the person maintaining the HTTP wrapper may receive questions they cannot answer about customer-facing behavior.

Use a bounded checklist, then verify one workflow

Before closing the discovery pass:

  • Record searched repositories, branches, and environments.
  • Search hostnames, paths, configuration keys, SDKs, and operation names.
  • Inspect generated clients and their source specifications.
  • Trace wrappers, dynamic configuration, jobs, and event consumers.
  • Compare findings with runtime evidence and document its limits.
  • Assign workflow owners and keep unresolved questions visible.

The next useful step is to select one inventory entry and verify its response assumptions against the provider’s announced change. This turns a list of matches into a focused engineering investigation without claiming complete coverage.

GhostImpact helps teams understand API changes, map producer-to-consumer dependencies, and investigate potential downstream impact. It supports that investigation; it does not replace testing or engineering judgment. Explore GhostImpact or discuss a project.