How do teams discover unknown/unused endpoints (ghost or zombie APIs) across microservices and third-party integrations?
AI Application Security

How do teams discover unknown/unused endpoints (ghost or zombie APIs) across microservices and third-party integrations?

11 min read

Most teams only realize they have ghost or zombie APIs after an incident: a “we thought that service was decommissioned” postmortem, a third‑party token that never expired, or a forgotten internal endpoint that becomes the attacker’s easiest pivot. In modern microservices and AI-heavy stacks, the real question isn’t if you have unknown/unused endpoints, but how fast you can discover and contain them in live traffic.

This guide breaks down how teams actually do that today—what works, what doesn’t—and why runtime-native discovery (not just static inventory) is now the critical control for ghost/zombie APIs across microservices and third‑party integrations.


Why ghost and zombie APIs exist in microservice and third‑party-heavy stacks

In microservice and agentic environments, APIs sprawl faster than any CMDB or OpenAPI catalog can keep up:

  • Service churn is constant. Teams spin up services for experiments, feature flags, and migrations, then “turn them off” in code—but the ingress paths and tokens often survive.
  • Versioning leaves old paths behind. /v1 endpoints hang around “just in case” after /v2 ships, and nobody ever sets a real sunset date.
  • Third‑party integrations are sticky. OAuth tokens, webhooks, and SDK callbacks stay configured long after the initial integration owner leaves the org.
  • Infrastructure adds hidden entry points. API gateways, service meshes, and sidecars expose admin/health/debug paths that don’t show up in your OpenAPI or Terraform.
  • AI and agents amplify the sprawl. Agentic workflows, MCP tools, and internal AI assistants call internal APIs your security team has never seen and didn’t design.

Result: your “API inventory” is usually a subset of reality. The unknown surface—the cloud within the cloud—is where ghost/zombie APIs hide.


What teams try first (and why it isn’t enough)

Most organizations start with the tools they already have. These approaches help, but each has blind spots.

1. Static asset inventories and service catalogs

Teams often turn to:

  • OpenAPI/Swagger spec repositories
  • Internal service catalogs (Backstage, homegrown UIs)
  • IaC repos (Terraform, Helm charts, Kubernetes manifests)

Problem: They show what should exist, not what actually receives traffic.

  • Specs are stale or missing for legacy services.
  • Decommissioned endpoints stay in inventories long after traffic stops.
  • Shadow services never get registered in catalogs.

You can’t discover unknown/unused endpoints from systems that only know about declared ones.

2. Perimeter-focused API gateways and WAF logs

Next, teams mine:

  • API gateway logs (Kong, Apigee, AWS API Gateway, NGINX, Envoy)
  • WAF and load balancer logs

You can:

  • List hostnames, paths, and methods that see traffic.
  • Flag “obvious” unused paths that no longer show up in recent logs.

Problem: This is still perimeter-only.

  • East–west traffic never hits the gateway/WAF.
  • Internal services talking over mesh (Istio/Linkerd), gRPC, or raw TCP stay invisible.
  • Agent-to-service and MCP-based calls often bypass traditional ingress completely.

Ghost APIs inside the cluster, between services, and across MCP/agent toolchains are still dark.

3. Code search and static analysis

Security and platform teams also try:

  • Repo-wide searches for @RestController, Route, GET /foo, etc.
  • Static analysis tools that infer endpoint definitions from code

This can reveal:

  • Hardcoded routes not published in OpenAPI.
  • Old handlers that never got deleted in refactors.

Problem: Code only tells you what could be reachable, not:

  • Which version is live behind traffic splitters.
  • Whether the endpoint still receives real workloads.
  • Which third‑party integrations and agents are actually calling it.

You risk burning time on “dead in practice” code while missing live endpoints created via configuration or dynamic routing.

4. Periodic “API discovery projects”

Many orgs end up with multi-quarter initiatives:

  • Manually mapping services and endpoints in spreadsheets.
  • Interviewing service owners and product teams.
  • Reconciling gateway configs, OpenAPI docs, and code references.

These are brittle by design:

  • They’re out of date the moment they’re published.
  • They don’t cover new services and AI/agent workflows that appear weekly.
  • Nobody has time to repeat them continuously.

The pattern is always the same: static inventories drift; reality keeps moving.


What actually works: runtime-native API discovery

To reliably discover unknown/unused endpoints (ghost/zombie APIs) across microservices and third‑party integrations, you need runtime-native discovery:

Observe real traffic inside your runtime, build a live blueprint of every endpoint and caller, and keep it updated automatically.

Think of this as shifting from a CMDB mindset to a packet+identity+process mindset:

  • Packet: What host, path, method, protocol, and parameters?
  • Identity: Which service, user, NHI, or token is calling?
  • Process/context: Which pod, deployment, MCP tool, or agent workflow is behind the call?

This is exactly the problem we designed Operant to solve: discovering the “cloud within the cloud” and then enforcing controls inline. But regardless of tool, the principles are the same.


Core capabilities you need to find ghost and zombie APIs

1. Cluster-wide, inline observation of runtime traffic

You need visibility beyond the WAF:

  • Kubernetes-native deployment.
    • Run at the pod/node level with a single step Helm install.
    • See traffic on service meshes, sidecars, and internal load balancers.
  • Protocol awareness.
    • HTTP/HTTPS plus gRPC, WebSockets, and streaming APIs.
  • East–west coverage.
    • Internal service calls, not just north–south ingress/egress.

This is how you surface internal-only endpoints that never touch the gateway but are still reachable from compromised workloads or agents.

2. Automatic endpoint and service cataloging

Instead of hand-maintained spreadsheets, you want an engine that:

  • Discovers endpoints from live traffic.
    • Host, path, method, status codes.
    • Automatically infers parameter shapes and auth patterns.
  • Builds a live service and API blueprint.
    • Which service exposes each endpoint?
    • Which other services, agents, and third parties call it?
  • Classifies endpoints by usage.
    • Active vs. inactive over configurable time windows.
    • Internal vs. external, machine vs. human vs. agent traffic.

In Operant, this shows up as the live API blueprint and discovery catalogs—the first step before you decide what to prune or lock down.

3. Identity-aware enrichment (users, services, agents, NHIs)

To distinguish “unused” from “quiet but critical,” you need identity:

  • Service identities.
    • Map calls to deployments, namespaces, and service accounts.
  • User identities.
    • Correlate traffic to OAuth2/OIDC claims, tenants, or organizations.
  • Agent and MCP identities.
    • Know when a request is coming from an AI agent, MCP tool, or downstream model.
  • Third‑party identities.
    • Who owns this token, this webhook, this credential?

This lets you say things like:

  • “This endpoint is only used by a deprecated service account.”
  • “This path is only called by our MCP server via a single tool.”
  • “No human or production workload has hit this endpoint in 60 days.”

Identity-aware mapping is what separates safe cleanup candidates from hidden critical dependencies.

4. Usage-based classification: ghost vs zombie vs active

Once you have runtime data and identities, the engine should continuously classify:

  • Active endpoints
    • Recently used in production workflows.
    • Called by known services, users, or agents.
  • Zombie APIs
    • Still reachable and occasionally used.
    • Attached to deprecated versions, legacy clients, or unmanaged agents.
  • Ghost APIs
    • Reachable in theory (DNS, routing, or service discovery exists).
    • No legitimate traffic over a defined period.

Operant’s runtime graph does this automatically, so you can filter by:

  • “Endpoints not used in last N days”
  • “Endpoints only called by dev/staging/test workloads”
  • “Endpoints only called by unmanaged agents or unknown clients”

This is where you find the real risk: endpoints that can be abused but nobody is watching.

5. Inline enforcement for containment and cleanup

Discovery without enforcement is just observability. To actually reduce risk from ghost and zombie APIs, you need controls that operate inline:

  • Block or rate-limit ghost endpoints.
    • Deny traffic to endpoints with no legitimate usage in the last X days.
    • Rate-limit or challenge suspicious traffic patterns.
  • Segment zombie APIs into trust zones.
    • Restrict who can call them (specific namespaces, identities, MCP tools).
    • Enforce allowlists/denylists while you migrate off them.
  • Auto-redact sensitive data at runtime.
    • For endpoints you can’t kill yet, redact PII/PHI in-line as it flows.
  • Apply NHI-aware policies.
    • Lock down endpoints that carry natural human identifiers (user emails, SSNs, patient IDs) by caller identity and purpose.

Operant packages this into 3D Runtime Defense (Discovery, Detection, Defense) so you move from “we know we have zombie APIs” to “we’ve fenced them off, and we’re watching attempts in real time.”


How teams actually implement ghost/zombie API discovery in practice

Here’s a pragmatic adoption pattern that doesn’t turn into another “instrumentation project.”

Step 1: Deploy runtime discovery in minutes, not quarters

Look for:

  • Single step Helm install. Zero instrumentation.
    • No code changes, no sidecar rewrites.
    • Should work across EKS/AKS/GKE/OpenShift.
  • Immediate value on live traffic.
    • Within minutes, you should see:
      • All services and APIs observed.
      • Initial mapping of callers and endpoints.

Operant was built from the start for this: Kubernetes-native, installs in a single step, starts building your live blueprint in <5 minutes.

Step 2: Baseline your real API surface

Use the live blueprint to:

  • Compare runtime reality vs. declared inventory.
    • Which endpoints appear in traffic but not in OpenAPI specs?
    • Which services are sending or receiving traffic but have no entry in your catalog?
  • Identify unmanaged or “shadow” services.
    • Namespaces or deployments that show up in runtime but no one owns on paper.
  • Map third‑party calls.
    • Outbound calls to SaaS and partner APIs.
    • Inbound calls from webhooks and SDKs.

This gives you the first, honest picture of your API footprint.

Step 3: Flag candidate ghost and zombie APIs

Now apply time and identity windows:

  • Ghost candidates
    • Endpoints with no observed traffic over your decommission horizon (30–90 days).
    • Endpoints exposed only on dev/test/staging domains that still resolve in prod.
  • Zombie candidates
    • Old versions (/v1) still receiving low-volume traffic.
    • Endpoints only called by:
      • Deprecated clients.
      • Unknown or unmanaged agents.
      • Service accounts flagged for retirement.

In Operant, this is a query or filter in the catalog, not a multi-week log-mining exercise.

Step 4: Add runtime guardrails before you rip anything out

Before you delete code or shut down services:

  • Apply stricter runtime policies.
    • Limit who can call suspected ghost/zombie endpoints.
    • Block requests from unknown identities or unapproved networks.
  • Monitor for attempted access.
    • If you suddenly see bursts of traffic to a guarded ghost endpoint, treat it as a detection event.
    • This can surface attackers probing for forgotten paths.
  • Auto-redact sensitive payloads.
    • If the endpoint touches PII/PHI, redact data inline.
    • This buys you time to migrate clients without exposing users.

This is where Operant’s inline enforcement matters: you’re not waiting on a firewall change or rollout; you’re actively defending while you validate and clean up.

Step 5: Decommission safely, with auditability

Once you’re confident:

  • Turn ghost endpoints into hard blocks.
    • Enforce deny-by-default on endpoints with no legitimate traffic.
  • Schedule version sunsets.
    • For zombies, coordinate with remaining consumers:
      • Use runtime logs to identify exactly who needs to migrate.
      • Provide concrete timelines and proofs of last use.
  • Log all decisions for compliance.
    • Keep a history: when an endpoint was discovered, flagged, contained, and finally decommissioned.

Operant’s runtime catalog and policy history provide that audit trail, mapped against frameworks like OWASP API Top 10, NIST 800, and PCI DSS V4 where relevant.


Special case: ghost/zombie APIs in MCP, agents, and AI-heavy stacks

As teams add agentic workflows and MCP, the ghost/zombie problem gets a new twist:

  • MCP tools exposing APIs you didn’t treat as APIs.
    • File systems, vector DBs, code tools now behave like RPC endpoints behind agents.
  • Unmanaged agents in SaaS and dev tools.
    • Agents in IDEs, CRMs, and ticketing systems call internal APIs from places you don’t monitor.
  • AI NHIs (natural human identifiers) stitched across systems.
    • Agents correlate emails, usernames, and IDs across multiple APIs.

To handle this, runtime discovery has to:

  • Detect MCP connections and tools automatically.
    • Build an MCP Catalog: which tools, servers, and clients are live.
    • Map which internal APIs each tool touches.
  • Label agent-originated traffic.
    • Distinguish human vs agent vs service calls.
  • Apply NHI-aware controls.
    • Block or redact NHI exfiltration from ghost/zombie endpoints.
    • Enforce trust zones so agents can’t reach legacy or deprecated APIs by default.

This is exactly where Operant’s Agent Protector, MCP Gateway, and AI Gatekeeper™ layer over the base runtime discovery: they extend the same ghost/zombie discipline to agent and MCP surfaces, not just traditional REST/gRPC services.


Putting it together: a practical decision framework

If you’re asking how teams discover unknown/unused endpoints (ghost or zombie APIs) across microservices and third‑party integrations, the core decisions are:

  1. Stop relying on static inventories alone.
    Specs, catalogs, and CMDBs are necessary context, but they’ll never be complete or current.

  2. Move discovery into the runtime.
    Deploy a Kubernetes-native, inline engine that sees east–west traffic, agent calls, and third‑party flows without code changes.

  3. Enrich with identity and usage windows.
    Classify endpoints by actual callers and activity levels so “unused” means something concrete.

  4. Contain before you decommission.
    Use inline blocking, rate limiting, trust zones, and auto-redaction to fence off ghost/zombie APIs before ripping out code.

  5. Extend the model to agents and MCP.
    Treat MCP tools and AI agents as first-class callers with their own catalogs, trust zones, and NHI-aware controls.

This is the pattern we see work repeatedly: discover the cloud within the cloud, defend it in real time, and then safely reduce it.


Next Step

If you want to see what your own ghost and zombie APIs look like on live traffic—across microservices, third‑party integrations, and agent workflows—you don’t need a six-month project.

Get Operant running with a single step Helm install, let it observe for a short window, and review the live API blueprint and ghost/zombie candidates with your team.

Get Started