Unknown APIs create five security gaps

Not knowing every API you run means getting the protection scope itself wrong. A test API missing from the documentation, an old version, an internal integration, or a temporary endpoint can keep working while sitting outside security review, patching, observation, incident response, and retirement. OWASP API9:2023 explains that missing inventory and retirement management leaves old API versions in place and raises the risk of sensitive data exposure and system compromise.[1] NIST likewise holds that without an accurate inventory it is hard to protect an organisation's APIs consistently. It describes APIs that are undocumented or that skipped the normal review process as shadow APIs, and APIs that were replaced but never fully removed as zombie or deprecated APIs.[2]

First, they fall outside the protection scope. Policy and review are usually designed around known assets. An API absent from the inventory is easy to miss in scoping, change review, vulnerability response, and observation. Endpoints built for internal, debug, or test purposes and left in production through a side path may well have passed through a weaker process than a formal API.[2]

Second, old versions survive. Deploying a new version does not automatically remove the old one. Where consumers remain or nobody owns retirement, the old endpoint keeps being called. Old versions drift out of the current development and review flow and stop receiving patches and policy improvements.[1]

Third, you lose sight of which data flows where. Knowing the host and path is not enough. You need to know what data moves, whether it reaches an external organisation or third-party service, and whether that flow is still needed. OWASP recommends recording the data exchanged with third-party APIs along with roles, sensitivity, and business need.[1]

Fourth, an incident has no owner. If the API exists but nobody is accountable today, it is unclear who decides to block, fix, or retire it. The past author in the repository and the current operator are often different people. Even a recorded team name does not amount to an assigned owner if that team never accepted the responsibility.

Fifth, an API you thought was retired becomes dangerous again. Deleting it from documentation, or seeing no recent traffic, does not finish retirement. If any one of DNS, load balancer, runtime route, serverless function, message consumer, or deployment manifest remains, it can be called again. Retirement is confirmed by evidence that it can no longer be reached or executed, not by "we cannot see it any more".

An API inventory reconciles four layers

An API inventory is not a spreadsheet built from a one-off URL sweep. It has to be an operating register that continuously reconciles what you declared you would build, what is actually deployed, what was observed at runtime, and who is accountable for what purpose. NIST also recommends reconciling declared specifications against live traffic to find the difference between what is deployed and what should be deployed.[2] Each layer answers a different question.

Evidence from the four layers converges into normalisation and correlation. That is where a stable API identity is formed and where evidence and confidence are recorded together. The result is the API register, which sorts each API into managed, shadow candidate, orphan candidate, or zombie candidate and sends it to manage, migrate, retire, or verify.

No single layer can be a complete source of truth. An OpenAPI document describes the declaration of an HTTP API but proves neither actual deployment nor the absence of endpoints missing from the document. As of 21 August 2026 the latest official OpenAPI version is 3.2.0.[3] Gateway logs likewise show only the traffic that crossed that gateway. Another gateway, a directly exposed origin, internal RPC, a message broker, an endpoint not called during the observation window, or a path missing telemetry all stay invisible. The output of a scanner or discovery product is therefore one observation source. Given that NIST requires specification, runtime, ownership, and live traffic to be reconciled together, the practical conclusion of this article is that no single tool produces a 100% complete API inventory.[2]

Layer
Question it answers
Main evidence
DeclaredWhat did we decide to build and run?OpenAPI, AsyncAPI, .proto, GraphQL schema, WSDL, repository, catalog, route definitions, code
DeployedWhat is actually deployed and reachable in each environment?Gateway routes, load balancer, DNS, Kubernetes, service mesh, serverless, runtime routes, broker, topic, and queue configuration
ObservedWhich calls or messages were actually observed?Access logs, traces, network observation, runtime logs, broker metrics, first seen, last seen
GovernedWho is accountable, why, and in what managed state?Owner, business purpose, data sensitivity, authentication category, exposure, version, lifecycle, retirement
The questions each of the four inventory layers answers and its main evidence — the reconciliation guidance of OWASP API9:2023 and NIST SP 800-228 split by layer (2026-08)
How the service works

Inspect and protect requests before they reach the service — Review request and blocking records, tune protection rules and manage certificates and access controls.

Do not put only REST APIs in the inventory

Normalising APIs as HTTP method plus URL path drops every interface outside REST. Each interface type carries different declared evidence and a different recommended inventory unit.

For HTTP and REST, the declared evidence is OpenAPI, route code, and framework annotations, and the unit is host scope plus method plus normalised path plus version. For GraphQL it is the schema, SDL, or introspection snapshot, and the unit is the endpoint plus operation type plus the significant fields and mutations. For gRPC it is the protocol buffer .proto, and the unit is the fully qualified service plus RPC method plus version. For message-driven APIs it is AsyncAPI, broker configuration, and producer and consumer code, and the unit is broker scope plus channel, topic, or queue plus operation plus message type. For SOAP it is the WSDL and service configuration, and the unit is service plus operation plus version. For WebSocket it is AsyncAPI or a separate contract, and the unit is the connection endpoint plus message operation.

OpenAPI is a specification for HTTP APIs, and message-driven APIs use a separate format such as AsyncAPI. gRPC generally declares services and RPC methods in a .proto file.[3] This is not merely a formatting difference. GraphQL can hold many queries and mutations behind one URL. A message-driven system can process sensitive data with no HTTP endpoint at all. Without matching the inventory unit to the technology, you end up knowing the host while not knowing the operations.

What a mismatch across the layers means

A mismatch between layers is the start of an investigation, not the conclusion. The third column of the table below records the hasty judgements that come up most often in practice.

Observed state and lifecycle state must be separate fields. observed_state is one of active, dormant, unseen, or unknown. lifecycle_state is one of active, deprecated, retiring, or retired. Having no recent calls is an observation state; it proves neither a retirement decision nor technical removal.

Finding
First reading
Conclusion not to jump to
Next action
All four layers agreeLikely a managed APIThat it is therefore safeRe-confirm current owner, lifecycle, and evidence
Present in deployed or observed, absent from declared and governedShadow candidateThat it is malicious or unauthorised on discoveryConfirm deployment origin, purpose, and owner, then register or remove
The API exists but no owner has accepted accountabilityOrphan candidateThat the repository author is the current ownerAssign business and technical owners separately
Deprecation or retirement evidence exists but it is still deployed or observedZombie candidateDeclaring it a zombie because recent traffic is lowCheck consumers, routes, runtime, and the retirement schedule
Present in declared, absent from deployed and observedPlanned, already retired, stale documentation, or an observation gapDeclaring it shadowCheck deployment history and how current the documentation is
Present in deployed but never observedDormant API or observation gapDeclaring it retired because there is no trafficVerify the observation window and telemetry coverage
Observed but no deployment source foundAn unknown route or a failed source mappingDismissing it as a logging errorTrace back through DNS, network, runtime, and proxy paths
Governed says retired but it remains deployedA failed retirement procedureDeciding it is fine because nothing calls itConfirm removal of reachability and consumer migration
What a mismatch across the four layers means, and the conclusion not to jump to — next action per finding (IXC review form)

Telling shadow, orphan, and zombie apart

The scope of these three terms varies by source and organisation. NIST describes internal, debug, test, and ad hoc APIs that are undocumented or skipped normal development and review as rogue or shadow APIs. It also describes APIs that were replaced but never fully removed, through unmigrated consumers or absent ownership, as zombie or deprecated APIs. For orphans, orphaned endpoint appears in the reconciliation guidance, but the document reviewed here offers no separate standalone definition.[2] The term definitions below add this article's practical criteria on top of that description.

The three classifications are not mutually exclusive. An undocumented API with no owner is both shadow and orphan. A retirement target left without an owner is both zombie and orphan. A classification is an operating state that requires investigation, not a delete command.

Shadow API
A shadow API is one with deployed or observed evidence that is not linked to an approved declared and governed record. One stale specification, or an owner who has not replied yet, is not enough to classify it.
Orphan API
An orphan API is one that exists without an owner who has been assigned and has accepted responsibility for change, incident response, and retirement. A departed author or one failed contact attempt is not enough to classify it.
Zombie API
A zombie API is one with confirmed deprecation, retirement, or replacement intent that is still deployed or still reachable and callable. Low recent traffic is not enough to classify it.

The minimum schema of an API register

A register that stores only URLs cannot perform reconciliation. At minimum you need ten groups of fields. OWASP also recommends recording per-host environment, network access, and version, along with the role, exchanged data, and sensitivity of third-party services.[1] NIST requires specification, ownership, and runtime information to be managed together and reconciled against live traffic.[2]

One record looks like this. With api_id api:fulfillment:inventory-sync:v1, identity carries the name inventory-sync, direction provided, protocol_style grpc, interface_key fulfillment.InventorySyncService, and version v1. Declared carries spec_type protobuf, the spec_ref of the .proto file, repository_ref, spec_digest, and declared_at. Deployed carries environment production, exposure internal, runtime_ref, deployed_version, deployment_state running, and last_deployed_at. Observed carries observation_sources such as service_mesh_trace and runtime_log, first_seen_at, last_seen_at, observation_window, observation_confidence, and observed_state. Governed carries accountable_owner, technical_owner, owner_attested_at, business_purpose, business_criticality, data_classification, authentication_category, expected_access, lifecycle_state, deprecation_at, retirement_target, and replacement_ref. Reconciliation carries status, findings, evidence_refs, checked_at, and next_review_at, and security carries record_classification, export_policy, and credential_material_present.

authentication_category records only the category of the authentication method. Tokens, secrets, private keys, cookie values, and connection strings must never be copied into the register.

Group
Minimum fields
Purpose
Identityapi_id, name, direction, protocol_style, interface_key, versionLink records from different sources to the same API
Declaredspec_type, spec_ref, repository_ref, spec_digest, declared_atConfirm the expected contract and its change history
Deployedenvironment, exposure, runtime_ref, deployed_version, deployment_state, last_deployed_atKnow which runtime is actually reachable
Observedobservation_sources, first_seen_at, last_seen_at, observation_window, observation_confidence, observed_stateRecord what was observed, when, and from which source
Ownershipaccountable_owner, technical_owner, owner_attested_atSeparate business accountability, technical ownership, and the time of attestation
Purpose and databusiness_purpose, business_criticality, data_classification, data_flowsJudge whether the API is needed and what data risk it carries
Access contextauthentication_category, expected_access, exposureRecord the access method and expected caller scope rather than the credential itself
Lifecyclelifecycle_state, deprecation_at, retirement_target, replacement_refTrack version replacement and retirement
Reconciliationreconciliation_status, findings, evidence_refs, checked_at, next_review_atManage mismatches, their basis, and follow-up review
Register securityrecord_classification, export_policy, credential_material_presentControl the sensitivity of the inventory itself and its export
Minimum fields of an API register — the ten groups reconciliation requires (IXC review form)

Closing the scope of the first inventory

Building the first API inventory means closing sixteen items. Did the scope include public, partner, and internal APIs? Did it include staging, test, preview, and legacy environments as well as production? Did it include both APIs you provide and APIs you consume? Did it include GraphQL, gRPC, SOAP, WebSocket, and message-driven APIs as well as HTTP and REST? Did you decide the unit by which an API is identified? Did you collect declared sources such as specifications, repositories, catalogs, and route code? Did you collect deployed sources such as DNS, load balancers, Kubernetes, serverless, and runtime routes? Did you record observed sources such as logs, traces, network, and brokers, along with the observation window? Did you normalise environments, versions, and aliases of the same API? Did you assign business and technical owners separately? Did you classify business purpose, data sensitivity, data flow, and exposure? Did you record deprecated, retiring, and retired states and their replacements? Did you send shadow, orphan, and zombie candidates to an investigation queue rather than deleting them? Did you configure register access rights, export policy, and audit logging? Did you confirm that no credential material entered the register? Did you set the next reconciliation trigger and its reviewer?

How the service works

Operations connected from observation to improvement — Respond using service indicators and alerts, then connect change records and incident reviews to improvements.

Update the register on every change

An inventory is harder to keep than to build. Define triggers so the register is updated whenever something changes.

There is no reason to apply one review cadence to every API. APIs with external exposure, high data sensitivity, frequent change, or high business importance need faster reconciliation. Conversely, even a stable and isolated API does not carry permanently valid owner and lifecycle evidence.

Trigger
Layers to reconcile
Automatic or manual check
Spec, schema, or .proto changeDeclared ↔ GovernedVersion, owner, lifecycle, blast radius
Repository mergeDeclared ↔ DeployedWhether route additions and removals match the deployment manifest
Deploy or rollbackDeployed ↔ DeclaredDifference between the deployed and declared version
DNS, LB, gateway, Kubernetes, or serverless changeDeployed ↔ GovernedDifference between new exposure paths and approved exposure
New runtime traffic or trace observedObserved ↔ Declared and DeployedUnregistered interfaces or unexpected callers
Reorganisation or team ownership changeGoverned ↔ allWhether the owner still accepts accountability
Deprecation or sunset date reachedGoverned ↔ Deployed and ObservedWhether the retirement target is still deployed and called
Periodic attestationAll four layersCurrency of purpose, sensitivity, version, owner, and evidence
Triggers that update the register when something changes — the layers to reconcile and what to confirm (IXC review form)

Eight steps from discovery to retirement

The first step is discovery. Preserve the discovery source, timestamp, environment, and raw evidence alongside each new API candidate. "An API was discovered" and "we know what this API is" are different states.

The second is normalisation. The same API is represented differently across sources. Align REST as method plus normalised path plus host scope, GraphQL as endpoint plus operation type plus significant fields, gRPC as fully qualified service plus method, and message-driven as broker scope plus channel, topic, or queue plus operation. Keep environment and version separable from identity so they can be compared.

The third is correlation. Link declared, deployed, and observed records that point at the same API. Record a confidence on automatic matches and never silently overwrite conflicting evidence.

The fourth is owner assignment. Separate the accountable_owner who judges business need from the technical_owner who implements and operates. Where no owner exists today, classify it as an orphan candidate and escalate. Deleting immediately because nobody owns it stops consumers and business work still relying on it.

The fifth is classification. Confirm provide or consume direction, public, partner, or internal exposure, business purpose, data classification and external data flows, authentication category, version and lifecycle, and shadow, orphan, or zombie candidacy.

The sixth is the manage-or-transition decision. An API that is genuinely needed joins the register, specification, ownership, and observation scope. A duplicated or aged API gets a consumer migration, replacement, and retirement plan.

The seventh is retirement execution. Retirement is not deletion from documentation. Confirm consumer migration, route and DNS removal, runtime resource shutdown, revocation of credentials, permissions, and integrations, updates to specifications, catalogs, and operating documents, a check for unexpected calls in observation sources, and the closure of rollback and exception plans.

The eighth is retirement verification. Do not declare completion from last_seen alone. You need evidence that reachability has been removed from the deployed layer, that the governed record was approved as retired, and that the required consumer migration finished.

The API inventory is itself a sensitive asset

A well-built API inventory is useful to an attacker too. Internal hosts and environments, versions, service names, owners, authentication categories, data classification, external data flows, and retirement states add up to something close to a map of the organisation's attack surface. The register and the public API documentation must not be treated as the same thing.

Eight rules apply. Restrict access with least privilege by role. Separate read access from export access. Put approval, audit logging, and a retention period on exports. Keep public documentation and the internal register apart. Never store credential material such as tokens, secrets, and private keys. Where needed, link only a non-sensitive reference from a secret manager. Apply a data classification to API records and attached evidence. Strip internal runtime references and owner information from anything shared externally.

OWASP recommends providing API documentation only to authorised users, and OpenAPI specifies security filtering that hides parts of a document according to access rights.[1]

When an API inventory is complete

An API inventory does not finish with one sweep of every URL. Eleven questions have to be answerable with evidence. What exists? Where is it deployed? Which protocol and version? What was observed recently? Who is accountable? Why is it needed? What data does it process? Who should it be exposed to? What is its current lifecycle state? When and how will it be retired? Do the four layers agree?

No specification, gateway log, or scanner answers all of those alone. The substance of an API inventory is not a list but an operating process that keeps finding and resolving mismatches. Only once the inventory is complete enough and kept current can you decide which controls fit each API's threats, data, and exposure conditions. That next step belongs to the companion article comparing the six API security controls.