· すべてのガイド
When APIs break, start with evidence—not guesses
Production API incidents rarely fail with a helpful single-line error. You get a 502 from the gateway, a 200 with {"success":false}, a truncated JSON body, or a JWT that "worked in Postman" but fails in the mobile app. The fastest teams treat debugging as a reproducible pipeline: capture the request, normalize the response, diff against known-good, validate contracts, then narrow to auth, routing, or payload semantics.
This playbook walks through that pipeline using Towalles browser-local tools. Nothing here uploads your captures to Towalles servers—still redact tokens and customer fields before pasting. For deeper JSON technique see json-formatting-guide; for URL query edge cases see url-api-debugging-guide.
Phase 1: Capture and parse the request
Reproduce minimally — One failing endpoint, one identity, one payload variant. Note method, path, query, headers (redact Authorization), and body.
Parse the URL — Paste the full URL into url-parser. Confirm scheme, host, path segments, and decoded query keys. Double-encoding (%252F) and plus-vs-space in query strings cause silent mismatches between client SDKs.
Encode sanity — If parameters look garbled, run suspect values through url-encoder and base64-encoder-decoder to see layering mistakes (Base64 inside URL encoding inside JSON).
Document findings in the incident doc: "Query filter decoded to empty string because client sent filter= with no value."
Phase 2: Normalize the response body
Format first — Minified error JSON hides the real failure three levels deep in error.details[0].message. Paste into json-formatter. If parse fails, you may have HTML error page, SSE chunk, or truncated gzip—check Content-Type and body length in Network tab.
Extract from LLM wrappers — AI gateways often return Markdown fences. Use llm-json-extractor before formatting when the body mixes prose and JSON.
Compare environments — Save staging and production responses (redacted). Format both, then json-diff for path-level changes. Teams frequently discover a missing data.version field or type change (number → string) that mobile parsers reject.
Example diff insight:
// staging
{ "user": { "id": 42, "tier": "pro" } }
// production
{ "user": { "id": "42", "tier": "pro" } }
ID type coercion breaks strict TypeScript clients—formatting alone would not flag it; diff does.
Phase 3: Auth and token inspection
When errors are 401/403 or intermittent:
- Paste bearer token into jwt-decoder (strip
Bearerprefix). - Check
exp,nbf,aud,iss, clock skew. - Confirm custom claims (
scope,roles) match route policy. - Remember: decoding is not verification—pair with server logs for signature failures.
For opaque API keys, use api-key-format-checker to identify provider format (Stripe, AWS, etc.) and ensure you did not swap test/live prefixes. Rotate if a live key appeared in a ticket attachment.
Chain with hmac-generator only for local test vector reproduction—never paste production signing secrets.
Phase 4: Contract and schema validation
Syntax-valid JSON can still violate OpenAPI. After formatting:
- Run structured-output-validator against your JSON Schema fixture.
- Use openapi-formatter to inspect component definitions if the field should exist per spec.
CI should own schema validation; during incidents, manual validator runs prove whether the bug is "server drift" vs "client assumption."
yaml-toml-config-guide mindset applies when config drives API behavior—convert deployment YAML with yaml-converter, format, diff against last release.
Phase 5: Time, cron, and idempotency
Scheduled jobs failing? Validate cron with cron-validator and expressions from cron-scheduling-guide. Off-by-one timezone errors mimic "random" API failures when batch windows misalign.
For retry storms, check idempotency keys in headers (often UUIDs)—generate test IDs with uuid-generator / ulid-generator and document expected header names in your API catalog.
Phase 6: Communicate and close
Incident comment template
- Request: method, path, query summary (no secrets)
- Response: status, formatted excerpt of error path
- Diff: what changed vs last known good
- Auth: exp/aud/iss summary (no raw token)
- Next owner: backend / gateway / client
Post-incident — Add a fixture to CI, link json-formatting-guide in runbook, rotate exposed credentials.
Tool chain cheat sheet
| Symptom | First tool | Then |
|---|---|---|
| Garbled query | url-parser | url-encoder |
| Unreadable JSON | json-formatter | json-diff |
| 401 after deploy | jwt-decoder | server verify logs |
| "Valid JSON", wrong shape | structured-output-validator | OpenAPI diff |
| Webhook body in chat | llm-json-extractor | json-formatter |
| Config regression | yaml-converter | json-diff |
Pitfalls that waste hours
- Debugging production with live refresh tokens in shared tabs.
- Assuming pretty JSON meant the server sent valid JSON (proxy may have rewritten body).
- Ignoring
Content-Encodingand double-parsed strings. - Skipping diff—eyeballing 200-line objects for one field change.
Towalles tool pages link to focused guides; this playbook ties them into an incident-ready sequence. Bookmark it for your next SEV-2 and run the phases in order before escalating to "maybe cache" theories.
Appendix: Worked example (synthetic data)
Symptom — Mobile app login fails after API gateway deploy; Postman with same bearer token returns 200.
Phase 1 — url-parser on https://api.example.com/v2/users/me?fields=profile,settings confirms path /v2/users/me (gateway added /v2 strip rule).
Phase 2 — json-formatter on mobile error body:
{"error":{"code":"PROFILE_SHAPE","details":[{"path":"user.id","expected":"number"}]}}
Phase 3 — jwt-decoder: exp valid; aud matches mobile-app; not an auth issue.
Phase 4 — json-diff staging vs production user object → production id became string after serializer change.
Resolution — Backend hotfix coerces ID to number; add schema test with structured-output-validator; document in api-debugging-playbook runbook link.
Total time saved by ordered tools vs random log grep: usually 30–90 minutes on cross-team incidents.
Appendix: Status-code routing table
| HTTP status | First hypothesis | Towalles first step |
|---|---|---|
| 400 | Malformed body/query | json-formatter or url-parser |
| 401 | Token missing/invalid | jwt-decoder |
| 403 | Scope/role mismatch | jwt-decoder claims + policy doc |
| 404 | Path/version drift | url-parser + deployment diff |
| 409 | Idempotency conflict | uuid-generator test headers |
| 422 | Schema validation | structured-output-validator |
| 429 | Rate limit | less tool—check retry-after header |
| 502/504 | Gateway/upstream | capture body anyway; may be JSON error envelope |
Appendix: curl → Towalles handoff
curl -sS -D - https://api.example.com/health -o /tmp/body.json
Copy body from /tmp/body.json into json-formatter; paste response headers into incident doc (redact cookies). Do not pipe live tokens into shell history—use env vars cleared after command.
Keeping curl for transport and Towalles for inspection matches choosing-local-online-tools hybrid pattern.