Back to guides

GUIDE / api

How to Test an API Without Documentation

Learn how to test an API without documentation: discover endpoints, reverse engineer contracts, design cases, validate auth, and avoid common blind spots.

By The Testing AcademyPublished July 9, 2026Updated July 9, 202616 min read

Releases do not pause because Swagger is stale or a mobile backend never published a public contract. How to test an API without documentation is the practical skill of rebuilding contracts from traffic, examples, and experiments while still covering status codes, payloads, auth, and business rules.

This guide shows a practical discovery-first workflow: find endpoints, reconstruct behavior, design test cases from evidence, validate auth and errors, capture a living contract, and avoid the mistakes that create false confidence. For foundational service-layer skills, pair this with the API testing tutorial. When you are ready to formalize cases, use how to write API test cases.

Why APIs Lose Documentation (and Why Testers Still Own Quality)

Documentation debt is common for several reasons:

  • The team moved fast and never wrote OpenAPI.
  • The public docs describe v1 while clients call v2.
  • Internal services were "temporary" and became permanent.
  • Mobile or SPA traffic is the only living contract.
  • Partners shared a PDF two years ago and never updated it.
  • Auth and edge cases live only in developer memory.

None of these excuses change user risk. An undocumented checkout API can still double-charge. An undocumented admin endpoint can still leak PII. Testing without docs is not about guessing forever. It is about turning observation into a testable model faster than the product breaks.

What "Without Documentation" Actually Means

Before you start, classify the gap. "No docs" is rarely absolute.

SituationWhat you still haveTesting implication
No OpenAPI, but active UIBrowser traffic, UI labels, user flowsCapture and map requests from real journeys
Partial portal docsSome endpoints, missing errors/authValidate documented paths, discover gaps
Internal service with logsRequest logs, metrics, error tracesUse logs as a discovery source
Partner API with sample JSONSample payloads onlyTreat samples as seeds, not full contracts
Truly dark serviceHost, maybe one path, no clientCareful probing plus stakeholder interviews

Your strategy should match the gap. A mobile backend with rich client traffic needs traffic capture first. A brand new microservice with no clients needs interviews, code review (if allowed), and careful exploratory probing.

Principles for Testing Undocumented APIs

1. Treat observation as a hypothesis

A response you saw once is not yet a contract. Promote patterns to expectations only after they repeat under controlled conditions, or after a product owner confirms the rule.

2. Prefer non-destructive discovery first

Start with OPTIONS, GET, and safe reads. Delay writes, deletes, and bulk operations until you understand identifiers, auth, and side effects.

3. Rebuild a living contract continuously

Every session should improve a collection, OpenAPI draft, or notes file. If discovery stays in chat threads, the next tester starts from zero.

4. Separate "what exists" from "what should exist"

You may discover an endpoint that returns data it should not. Testing without docs still includes security and authorization judgment, not only happy-path mirroring of the client.

5. Risk first, completeness second

You will not map every field on day one. Cover money, identity, auth, data integrity, and high-traffic flows before obscure admin filters.

Step-by-Step: How to Test an API Without Documentation

Step 1: Define scope and constraints

Write down:

  • Environment: staging, sandbox, production-read-only, local.
  • Permission: what probing is allowed.
  • Data sensitivity: PII, payments, secrets.
  • Goal: smoke coverage, regression suite, security pass, partner onboarding.

Without scope, discovery becomes endless surfing.

Step 2: Inventory known entry points

Collect anything that hints at an API surface:

  • Base URLs from config files, env vars, or mobile app settings.
  • Reverse proxy paths (/api, /v1, /graphql).
  • Client repositories if accessible.
  • Gateway dashboards, WAF logs, or APM traces.
  • Error emails and support tickets that quote endpoints.

Even a single base URL plus a login flow is enough to begin.

Step 3: Capture real client traffic

This is usually the highest value discovery method.

Browser apps

  1. Open DevTools Network panel.
  2. Filter XHR/Fetch.
  3. Exercise major UI journeys: login, list, create, update, delete, search, export.
  4. Export HAR or copy as cURL into Postman.

Mobile apps

  1. Route traffic through a trusted proxy in a test build.
  2. Capture HTTPS with certificate pinning disabled only in non-production builds you control.
  3. Map each screen action to request sequences.

Desktop or third-party clients

  1. Use a proxy or packet capture where policy allows.
  2. Note headers, cookies, tokens, and retry behavior.

Build a table as you capture:

JourneyMethodPathAuthNotable headersSample status
LoginPOST/auth/loginnoneContent-Type200
List ordersGET/orders?page=1BearerAccept200
Create orderPOST/ordersBearerIdempotency-Key201

Step 4: Reconstruct the resource model

From captured traffic, identify nouns and relationships:

  • Resources: users, orders, items, invoices.
  • Identifiers: id, uuid, slug, composite keys.
  • Relationships: order has line items, user has addresses.
  • Lifecycle: draft -> submitted -> paid -> cancelled.

Draw a simple model:

User
  └── Orders
        └── LineItems
        └── Payments

This model drives test design even before formal docs exist.

Step 5: Probe methods and content negotiation

For each discovered path, carefully check:

  • Allowed methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD.
  • Content types: application/json, form data, multipart.
  • Version headers or path versions: /v1, /v2, Accept-Version.
  • Query conventions: filter, sort, page, limit, include.

Example exploratory checks:

OPTIONS /orders HTTP/1.1
Host: api.example.test
GET /orders HTTP/1.1
Host: api.example.test
Accept: application/json
Authorization: Bearer <token>
GET /orders HTTP/1.1
Host: api.example.test
Accept: application/xml
Authorization: Bearer <token>

Record which methods return 200/201, which return 405, and which unexpectedly succeed.

Step 6: Reverse engineer authentication and authorization

Auth is where undocumented APIs hide the most risk. Study:

  • Login request and token shape (JWT, opaque token, session cookie).
  • Token refresh flow.
  • Required scopes or roles in responses.
  • Difference between missing token, expired token, and wrong role.
  • Admin-only paths that the UI never exposes to normal users.

Build a matrix:

ActorEndpointExpected outcome
AnonymousGET /orders401
BuyerGET /orders200 own data
BuyerGET /orders/{otherUserOrder}403 or 404
AdminGET /orders/{any}200

For deeper auth patterns, see API authentication testing.

Step 7: Infer validation rules from errors

Send controlled invalid inputs and capture messages carefully.

Examples:

  • Omit required fields.
  • Send wrong types ("quantity": "two").
  • Exceed length limits.
  • Use future dates where only past dates make sense.
  • Reuse unique keys.

Error bodies often reveal the real schema:

{
  "error": "validation_failed",
  "details": [
    { "field": "email", "code": "invalid_format" },
    { "field": "quantity", "code": "must_be_positive_integer" }
  ]
}

Turn each detail into a negative test case and a schema constraint note.

Step 8: Map status codes to behaviors

Do not assume textbook status codes. Observe and document actual behavior, then challenge unsafe choices.

Useful reference while interpreting responses: REST API status codes.

ObservedLikely meaningTest idea
200 on createNon-standard but possibleAssert body and side effect, note inconsistency
201 on createStandard createAssert Location/id
204 on deleteSuccess no bodyAssert resource gone
400 on bad JSONClient errorInvalid payload suite
401/403 mixAuth vs authzSeparate missing vs forbidden
404 for hidden resourcesSecurity through obscurityIDOR checks still needed
429Rate limitBurst and recovery tests
500 on edge inputServer bugReproduce and file defect

Step 9: Design test cases from the reconstructed model

Once you have resources, auth, and validation hints, write cases the same way you would with docs, but mark confidence levels.

IDTitleConfidenceSource of truth
TC-ORD-001Buyer creates valid orderHighUI + repeated 201
TC-ORD-002Missing productId rejectedMediumError detail observed
TC-ORD-003Buyer cannot read other buyer orderHighSecurity requirement + probe
TC-ORD-004Pagination default page sizeLowObserved only once

Promote low-confidence cases after confirmation. Do not silently treat every observation as guaranteed product law.

Step 10: Verify side effects, not only response bodies

Undocumented APIs often look fine in JSON while breaking downstream state.

Check:

  • Database or admin UI state (when allowed).
  • Emails, webhooks, queue messages.
  • Inventory decrements.
  • Idempotency keys preventing duplicates.
  • Cache staleness after updates.

A create endpoint that returns 201 with an id but never persists is a critical defect.

Step 11: Capture a living contract

Convert learning into one of:

  • Postman/Bruno collection with examples and tests.
  • Draft OpenAPI from traffic or manual authoring.
  • Markdown endpoint catalog in the repo.
  • Contract tests once consumer/provider boundaries are clear.

Minimal OpenAPI sketch from discovery:

openapi: 3.0.3
info:
  title: Discovered Orders API
  version: "0.1.0-draft"
paths:
  /orders:
    get:
      summary: List orders for current user
      parameters:
        - in: query
          name: page
          schema: { type: integer, minimum: 1 }
      responses:
        "200":
          description: Paginated order list
    post:
      summary: Create order
      responses:
        "201":
          description: Order created
        "400":
          description: Validation error

Mark it draft. Version it. Update it when production clients teach you something new.

Step 12: Automate the stable core

Automate only after expectations stabilize:

  1. Auth smoke.
  2. Critical CRUD happy paths.
  3. High-risk negatives (authz, payment validation).
  4. Schema checks for key responses.
  5. A few idempotency and pagination invariants.

Keep exploratory sessions for new builds. Discovery is continuous when docs remain weak.

Discovery Techniques Toolkit

Traffic-first discovery

Best when a client already exists. Fastest path to real field names and sequences.

Code-assisted discovery

If you can read the service code or client SDK:

  • Route tables and controllers list endpoints.
  • DTOs reveal required fields.
  • Middleware shows auth requirements.
  • Tests in the repo are accidental documentation.

Use code as a hint, still verify runtime behavior.

Error-message mining

Verbose errors in lower environments leak schema and business rules. Capture them, then confirm whether production is stricter or quieter.

Sequence diagram reconstruction

For multi-step flows (checkout, onboarding), record ordered calls:

1. POST /cart/items
2. POST /cart/coupons
3. GET  /cart/totals
4. POST /checkout/sessions
5. POST /payments/confirm
6. GET  /orders/{id}

Failures often live between steps, not inside a single call.

Differential analysis across roles

Call the same endpoint as guest, user, manager, and admin. Diff status codes and body fields. Authorization bugs show up as unexpected 200s or extra fields.

Parameter fuzzing with guardrails

Once a path is known, vary:

  • IDs (valid, invalid, other-tenant, SQL-ish strings carefully in test envs)
  • Enums (known values plus unknown)
  • Booleans as strings
  • Empty arrays vs null
  • Unicode and long strings

Fuzz to learn constraints, not to vandalize shared environments.

Worked Example: Undocumented Inventory Service

Imagine a warehouse SPA. There is no Swagger. You only know https://staging.example.test.

Session notes

  1. Login via UI captures POST /api/session returning { "token": "...", "role": "clerk" }.
  2. Inventory page calls GET /api/skus?limit=50.
  3. Editing quantity calls PATCH /api/skus/SKU-100 with { "onHand": 12 }.
  4. Export button calls GET /api/skus/export.csv.
  5. Admin user sees DELETE /api/skus/SKU-100 in a different build flavor.

Reconstructed expectations

CaseRequestExpected
Clerk listGET /api/skus200 array, no cost fields
Clerk patch validPATCH onHand 12200, onHand updated
Clerk patch negativeonHand -1400 validation
Clerk deleteDELETE403
Admin deleteDELETE204 and item gone
No token listGET401
CSV exportGET export.csv200 text/csv with header row

First automated smoke

// pseudo-test
test("clerk can list skus", async () => {
  const res = await api.get("/api/skus?limit=50", clerkToken);
  expect(res.status).toBe(200);
  expect(Array.isArray(res.body)).toBe(true);
  expect(res.body[0]).toHaveProperty("sku");
  expect(res.body[0]).not.toHaveProperty("unitCost");
});

You now have documentation in executable form.

Designing Coverage Without a Spec

Use risk-based categories:

Functional correctness

  • Create/read/update/delete where applicable.
  • Search/filter/sort.
  • Pagination defaults and bounds.
  • State transitions (cancel, approve, ship).

Contract shape

  • Required fields present.
  • Types stable.
  • Nullability consistent.
  • Unexpected breaking renames caught early.

Security and tenancy

  • Authn failures.
  • Authz matrix.
  • Object-level authorization (IDOR).
  • Mass assignment of privileged fields (role, price, isAdmin).

Resilience and abuse

  • Rate limits.
  • Oversized payloads.
  • Duplicate submits.
  • Partial failure retries.

Compatibility

  • Old clients vs new fields.
  • Optional headers.
  • Version routing.

Comparison: Documented vs Undocumented Testing Effort

ActivityWith solid docsWithout docs
Endpoint inventoryHoursDays of capture/probing
Expected resultsMostly givenHypotheses then confirmation
Auth matrixOften partialMust reverse engineer
Automation startFasterDelayed until stable observations
Defect styleDeviations from specDiscoveries of missing rules and unsafe defaults
Ongoing costMaintain suiteMaintain suite + living contract

Undocumented work is heavier up front. The payoff is that your test assets often become the best documentation the company has.

Collaboration Tactics When Specs Are Missing

Testers should not reverse engineer alone forever.

  • Schedule short contract interviews with backend owners.
  • Share your draft OpenAPI as a review artifact.
  • File "missing documentation" issues with severity based on consumer risk.
  • Ask product to confirm business rules you inferred from errors.
  • Propose consumer-driven contracts if multiple clients depend on the service.

A useful question in standups: "Which undocumented endpoint changed this sprint?" That alone prevents silent breakages.

Checklist: Testing an API Without Documentation

Use this before you call discovery "done enough" for a release:

  • Base URLs and environments listed
  • Major client journeys captured as requests
  • Resource model sketched
  • Auth mechanism and roles understood
  • Critical happy paths have expected results
  • High-risk negatives defined (authz, validation, money)
  • Status code map recorded for key endpoints
  • Side effects verified for create/update/delete
  • Living collection or OpenAPI draft updated
  • Smoke automation covers the top risks
  • Open questions escalated to owners

Common Mistakes When You Test APIs Without Documentation

Mistake 1: Copying the UI as if it were the full API

The UI may never call admin routes, bulk endpoints, or legacy methods still exposed publicly. Client coverage is a starting set, not the complete attack or integration surface.

Mistake 2: Turning one sample response into a rigid schema too early

Optional fields appear on some records only. Over-strict assertions then flake. Start with required core fields, then tighten after broader sampling.

Mistake 3: Ignoring authorization because happy paths work

If a buyer can complete flows, that does not mean object-level checks are safe. Always test access to other users' IDs.

Mistake 4: Testing only GET endpoints

Reads feel safe and easy. Many production incidents come from write paths, webhooks, and delete semantics.

Mistake 5: Leaving discovery notes outside the suite

Screenshots in a personal folder expire. Collections, contract drafts, and automated checks survive handoffs.

Mistake 6: Aggressive probing in production

Undocumented production APIs can still trigger real charges, emails, or legal issues. Prefer staging. If production is required, use read-only accounts and approved test tenants.

Mistake 7: Assuming 404 means "secure"

Some systems hide existence with 404 while still leaking timing or secondary endpoints. Combine status checks with broader tenancy tests.

Mistake 8: Never confirming inferred business rules

If you inferred "quantity must be positive" from one error, confirm whether zero is allowed for backorders. Wrong expected results create invalid bugs and missed bugs.

FAQ-Oriented Mini Patterns

"I only have a base URL. Now what?"

Start with GET /, GET /health, GET /api, GET /v1, and OPTIONS where allowed. Then search client bundles for path strings. Without a client or code, escalate for access to logs or a smoke UI.

"Responses are inconsistent. How do I write cases?"

Document variants. Example: order responses include payment only when status is paid. Parameterize expectations by state instead of forcing one universal body.

"Should I fail the build if the living OpenAPI drifts?"

Yes for critical consumers, once the draft is reviewed. Early in discovery, warn instead of fail. After agreement, treat breaking changes as release blockers.

Practice Path on QABattle

Theory sticks when you practice under constraints. Open QABattle battles or start free at sign-up and pick API challenges where the prompt is incomplete on purpose. Force yourself to:

  1. List only what you can observe.
  2. Write five cases with confidence tags.
  3. Automate two smokes.
  4. Record three open questions for a fictional API owner.

That workflow mirrors undocumented services at work.

Putting It All Together

To master how to test an API without documentation, stop waiting for a perfect Swagger file and build evidence systems instead:

  1. Capture traffic and inventory endpoints.
  2. Reconstruct resources, auth, and validation rules.
  3. Design risk-based cases with confidence levels.
  4. Verify side effects and authorization, not only JSON.
  5. Publish a living contract and automate the stable core.
  6. Keep discovering as clients and versions change.

Undocumented APIs punish teams that rely on memory. They reward teams that turn every probe into shared, executable knowledge. Use the API testing tutorial for fundamentals, how to write API test cases for case structure, and API authentication testing when tokens and roles get messy. Then keep sharpening on real battles in the app.

When you leave a service better documented than you found it, you did more than test. You reduced operational risk for every engineer who comes next.

FAQ

Questions testers ask

How do you test an API that has no documentation?

Start with discovery: capture traffic from the client, list reachable routes, probe HTTP methods, inspect auth flows, and rebuild a draft contract from real requests and responses. Then design cases for happy paths, validation, auth, errors, and side effects, and refine the contract as you learn.

What tools help when testing an undocumented API?

Use browser DevTools, proxy tools such as Charles or mitmproxy, Postman or Bruno for exploration, OpenAPI generators from traffic, and coded clients for automation. Logs, server error messages, and database state (when allowed) also reveal structure that docs would normally provide.

Is it safe to reverse engineer a production API for testing?

Prefer staging or dedicated test environments. If you must use production-like systems, stick to read-only probes first, avoid destructive writes, respect rate limits, and get permission. Undocumented does not mean unrestricted. Security and data rules still apply.

How do you know expected results without a formal contract?

Derive expectations from UI behavior, business rules, stable observed responses, error messages, status codes, and stakeholder confirmation. Treat early observations as hypotheses. Promote them to documented expectations only after repeated, consistent behavior or explicit product sign-off.

Should you write OpenAPI after reverse engineering?

Yes when the API will be reused or automated. A living draft OpenAPI or collection becomes the missing documentation, reduces tribal knowledge, and makes schema and status code checks maintainable. Keep it versioned and update it whenever reality diverges.

What is the biggest risk when testing undocumented APIs?

False confidence. You may cover the paths you observed while missing rare methods, hidden fields, auth edge cases, or destructive side effects. Pair discovery with risk-based prioritization, negative testing, and continuous capture of new client traffic.