How to Report API Bugs: Template, Examples and Severity

How to Report API Bugs: Template, Examples and Severity

Finding an API bug is half the job. The other half is reporting it so clearly that a developer can reproduce it in one minute, understand the impact and fix the right thing. A vague ticket like “Order API not working” bounces back and forth for days; a precise one with a cURL command gets fixed the same day. In this lesson you’ll learn the API bug report template that developers love, how to judge severity and priority, and see real examples, including genuine issues found during this course.

Quick answerA good API bug report contains: a specific title (method, endpoint, condition, wrong result), environment and build, preconditions (user, role, data), the exact request as a cURL command, the actual response (status, headers, body), the expected result with the source (spec, requirement), evidence (request/trace id, timestamp, logs), reproducibility, severity and priority, and the impact. Always remove real tokens and personal data before sharing.
Advertisement

Why API Bug Reports Are Different

UI bugs can be shown with a screenshot. API bugs live in requests and responses that nobody can see unless you capture them. That means:

  • The exact request matters: one header or one field type changes everything.
  • The exact response (status, headers, body) is the evidence.
  • Backend logs are searchable by request id and timestamp, so include them.
  • The same API serves web, Android, iOS and partners, so state which client or whether it’s reproducible directly.
Real-life example: the two-day ping-pong Ticket: “Payment fails sometimes.” Developer: “Works for me.” Tester: “Try again.” Two days later someone notices it fails only when the coupon field is null instead of missing. A cURL command with the actual body would have shown that in the first message.

The API Bug Report Template

FieldWhat to write
Title[METHOD] [endpoint] returns [actual] instead of [expected] when [condition]
EnvironmentQA / staging URL, build or version, date and time with time zone
PreconditionsUser and role, test data ids, feature flags
Steps / RequestcURL command (or Postman request) that reproduces it
Actual resultStatus code, relevant headers, response body (trimmed)
Expected resultExact status and body, with the reference (spec section, story, acceptance criteria)
EvidenceRequest/trace id, timestamp, screenshots of logs, HAR or Postman console export
ReproducibilityAlways / 3 of 10 / only with specific data
Severity / PriorityImpact on system / urgency to fix
ImpactWho is affected and how (users, money, data, security)
NotesWorkaround, first seen in build X, related tickets, your analysis
Advertisement

Writing a Great Title

Weak titleStrong title
Validation not workingPOST /users accepts age 17 (min is 18) and returns 201
Error in order APIPOST /orders returns 500 instead of 422 when quantity is negative
Security issueGET /orders/{id} returns another customer’s order (BOLA)
Wrong statusDELETE /cart/items/{id} returns 200 with empty body; spec says 204
Slow APIGET /products?category=books p95 latency 4.2 s (SLA 800 ms) on QA

A strong title lets a lead triage the bug without opening it.

Capturing the Request Correctly

  • Postman: Code (</>) → cURL. Make sure variables are resolved (check the Console).
  • Browser: DevTools → Network → right-click → Copy as cURL. Or save a HAR file for multi-request issues.
  • Playwright: attach request and response to the test report, or use the trace viewer.
  • Mobile: proxy the app through Charles, Proxyman or mitmproxy on a test device.
Sanitise before sharing Replace real tokens, cookies, API keys, passwords and personal data (names, phone numbers, Aadhaar/PAN, card numbers) with placeholders like <ADMIN_TOKEN>. Tickets are read by many people and often synced to other tools. Never paste production customer data.
Advertisement

Example 1: Validation Bug (Full Report)

Title:        POST /objects returns 500 when "ttl" is a JSON array instead of 422

Environment:  QA - https://qa.shop.example/api/v1, build 2026.11.3, 12-Nov-2026 15:20 IST
Preconditions: none (endpoint is public)

Request:
curl -i -X POST "https://qa.shop.example/api/v1/objects" \
  -H "Content-Type: application/json" \
  -d '{"name":"Bag","ttl":[60]}'

Actual:
HTTP/1.1 500 Internal Server Error
X-Request-Id: 9f2c1d7e
{"error":"Unhandled exception"}

Expected:
HTTP/1.1 422 with error.details[0].field = "ttl"
(OpenAPI: NewObject.ttl is integer 10-1800; API guidelines section 4: invalid input -> 422)

Reproducibility: 5/5. Same result for ttl = {}, true.
Severity: Medium (unhandled exception; no data impact)   Priority: P2
Impact: Any client sending a wrong type gets a 500; error monitoring is flooded.
Notes:  ttl = "60" (string) correctly returns 422, so only non-scalar types fail.

Notice the extra analysis in Notes. It narrows the cause to “non-scalar types” and saves the developer time.

Example 2: Security Bug (BOLA)

Title:        GET /orders/{id} returns other customers' orders (BOLA / IDOR)

Environment:  Staging, build 2026.11.2
Preconditions: Customer A (qa_cust_a) and Customer B (qa_cust_b), both role=customer.
               Order 70412 belongs to B.

Request (as A):
curl -i "https://staging.shop.example/api/v1/orders/70412" -H "Authorization: Bearer <TOKEN_CUSTOMER_A>"

Actual:   200 OK with B's name, phone, address and items.
Expected: 404 (or 403) and no data. (Security requirement SEC-12: users access only their own orders.)

Reproducibility: Always. Order ids are sequential, so any order can be read.
Severity: Critical   Priority: P1 (blocker for release)
Impact:   Personal data of all customers exposed to any logged-in user. Data protection risk.
Notes:    PATCH /orders/70412 as A returns 403 correctly, so only the read path lacks the ownership check.

Security bugs often go into a restricted ticket or a separate security queue. Follow your company’s disclosure process.

Advertisement

Example 3: Real Findings From This Course

While writing these lessons we tested real public services. Two genuine, reportable observations:

Stack trace in a public SOAP service

Title:   Divide with intB=0 returns SOAP Fault exposing stack trace and server file path
Service: http://www.dneonline.com/calculator.asmx (public demo calculator)
Actual:  HTTP 500, faultcode soap:Server, faultstring contains
         "System.OverflowException ... at Calculator.Divide(Int32 intA, Int32 intB) in G:\PleskVhosts\...\Calculator.asmx:line 19"
         plus header X-AspNet-Version: 2.0.50727
Expected: soap:Client fault with a safe message such as "intB must not be 0"; no stack trace, paths or version headers.
Severity: Medium (information disclosure, OWASP API8)

Inconsistent error format for unknown versions

The SQA Tools practice API returns its own error shape {"error":{"status","code","message"}} everywhere, except for unknown routes such as a wrong version, where the underlying framework answers with a different shape:

GEThttps://sqatools.in/wp-json/sqa-api/v1/../v9/users
curl -i \
  "https://sqatools.in/wp-json/sqa-api/v1/../v9/users"
GET https://sqatools.in/wp-json/sqa-api/v9/users
Actual:   404 {"code":"rest_no_route","message":"No route was found ...","data":{"status":404}}
Expected: 404 in the documented format {"error":{"status":404,"code":"not_found","message":"..."}}
Severity: Low   Priority: P3
Impact:   Clients that parse error.code break on this path.

Low severity, but exactly the kind of consistency issue a careful tester reports.

Severity vs Priority

SeverityPriority
MeaningHow bad the impact on the system or users isHow soon it must be fixed
Set byUsually the testerUsually product owner / lead
LevelsCritical, High (Major), Medium, LowP1 (now), P2, P3, P4
API exampleSeverityPriority
Payment API double-charges on retryCriticalP1
BOLA exposing customer addressesCriticalP1
Admin report export returns 500 for one rare filterHighP3 (used once a month, workaround exists)
Typo in error message shown to all users at launchLowP2 (visible, cheap to fix)
Error format inconsistent on unknown routesLowP3
Advertisement

Before You Click “Create”: Self-Check

  1. Did I reproduce it at least twice, ideally with a fresh token and fresh data?
  2. Is it really a bug? Check the spec, the story and recent changes. If the spec is unclear, raise a question rather than a bug.
  3. Is it a duplicate? Search existing tickets by endpoint.
  4. Did I isolate the minimum request that fails (remove unrelated fields)?
  5. Did I include request id/timestamp so logs can be found?
  6. Did I remove secrets and personal data?
  7. Is the expected result backed by a reference, not my opinion?

Automation Failures vs Real Bugs

When an automated API test fails, triage before reporting:

  • Product bug: the API changed behaviour against the spec. Report with the request from the test report.
  • Test bug: wrong expectation, hardcoded data, order dependency. Fix the test.
  • Environment issue: service down, expired test credentials, data reset. Notify the environment owner, don’t log a product bug.
  • Flaky: passes on rerun. Investigate timing, shared data and rate limits; don’t just add retries.

Playwright makes evidence easy: attach the response to the report on failure.

test('POST /objects returns 201', async ({ request }, testInfo) => {
  const res = await request.post(`${BASE}/objects`, { data: { name: 'Bag', ttl: 60 } });
  if (res.status() !== 201) {
    await testInfo.attach('response', {
      body: JSON.stringify({ status: res.status(), headers: res.headers(), body: await res.text() }, null, 2),
      contentType: 'application/json',
    });
  }
  expect(res.status()).toBe(201);
});
Advertisement

Communicating With Developers

  • Be factual: “returns 500” not “the API is broken”.
  • Offer analysis, not blame: “fails only for non-scalar ttl values” helps more than “validation is missing everywhere”.
  • For critical bugs, message the developer or lead directly as well as filing the ticket.
  • Retest promptly when fixed, on the same data plus related cases (fixes often break neighbours).
  • Close the loop: add an automated regression test so it can’t come back.
Advertisement

Interview Questions: API Bug Reporting

What do you include in an API bug report?

A specific title, environment and build, preconditions, the exact request as cURL, the actual status, headers and body, the expected result with a reference, request id and timestamp, reproducibility, severity, priority, impact and any analysis or workaround, with secrets removed.

What is the difference between severity and priority?

Severity is the degree of impact of the defect on the system or users; priority is the urgency of fixing it based on business needs. A high-severity bug can have low priority and vice versa.

Give an example of high severity and low priority.

A crash (500) in a rarely used admin export with an available workaround: technically severe but can wait for a later release.

Give an example of low severity and high priority.

A wrong brand name or spelling in an error message shown to every user on launch day: little functional impact, but needs fixing immediately.

Why include a cURL command in an API bug?

It reproduces the exact request, including method, headers and body, on any machine in seconds, removing ambiguity and “works on my machine” delays.

Why include a request id or timestamp?

It lets developers find the exact request in server logs and distributed traces across services, speeding up root-cause analysis.

What would you do if the developer says it’s not a bug?

Check the reference (spec, story, acceptance criteria) and share it. If requirements are unclear, involve the product owner to decide, and update the spec or tests based on the decision.

How do you decide if an automated test failure is a real bug?

Rerun and analyse: check whether the API behaviour changed against the spec, whether the test or data is wrong, whether the environment is unhealthy, or whether it’s flaky due to timing or shared data. Only product behaviour issues become bug reports.

How do you report a security vulnerability found in an API?

Follow the company’s security process: restricted ticket or security channel, minimal reproduction with test accounts, clear impact, no public sharing and no exploitation beyond proving the issue.

What is a good bug title format for APIs?

[METHOD] [endpoint] returns [actual result] instead of [expected result] when [condition], for example “POST /orders returns 500 instead of 422 when quantity is negative”.

Advertisement
View the full API testing syllabus