Explain why Tax MCP declined without making the user think the API failed or that a retry can bypass the boundary.
Product designers, support owners, and frontend engineers building review queues.
A decline only names the modeled boundary Tax MCP can see. It cannot detect income or facts a caller omitted.
Reference links: GET /api/mcp/tax-capabilities for the supported envelope, OpenAPI for request and response schema, roadmap feedback, changelog/release notes, support/contact, and terms.
Show the decline code, reason, next_action, and the workflow or route that declined.
Use neutral language: 'Needs preparer review' or 'Outside the supported envelope.'
Link to the supported envelope and roadmap feedback path from the review state.
Do not show a tax value, confidence score, or guessed result for the declined surface.
Do not auto-mint a new Idempotency-Key for the same body. The same unsupported input will decline again.
| State | HTTP | Billed | Retry safe | next_action | Client display guidance |
|---|---|---|---|---|---|
| Computed | 200 | Yes on metered customer plans | true with the same Idempotency-Key | none | Show computed figures with derivation and provenance. |
| Deterministic decline | 200 | Yes on metered customer plans | false for the same unsupported body | review_inputs | Show the reason and route to review; do not show a tax estimate. |
| needs_review | 200 | Yes on metered customer plans | true for replay; human review is still required | review_inputs | Show the review queue item, diff, reason, and provenance. |
| Validation error | 400 | No | false until request shape is fixed | fix_request_and_resubmit | Show a request-error state and tell the developer what field to fix. |
| Auth error | 401/403 | No | false until credentials are fixed | check_credentials | Ask the operator to check, rotate, or unsuspend the API key. |
| Quota or rate limit | 429 | No | quota: false; rate: true after backoff | upgrade_plan_or_wait_next_period or retry_after_backoff | Hard-stop quota or transient rate-limit message; do not overrun. |
| Idempotency replay | 200 | Once total | already replayed | none | Show the original result and reassure that replay did not double bill. |
| Idempotency mismatch | 409 | No | false with that key | use_new_idempotency_key | Client bug: same key was used for a different body. |
| Idempotency in progress | 409 | No | true with the same key after a short wait | retry_after_inflight_completes | Show in-progress and retry the same key. |
| Server failure | 500/503 | No | 500: false; 503: true after backoff | fix_request_and_resubmit or retry_after_backoff | Open support if persistent; do not show a computed result. |
First evaluators should be able to explain these states without private help before sending taxpayer-like payloads. Each row names the guide to read, the safe recovery behavior, and the privacy-safe telemetry event that can detect confusion.
| State to understand | Expected understanding | Primary guide | Safe recovery | Telemetry hook |
|---|---|---|---|---|
| Computed 200 | A computed 200 can show figures, provenance, legal_notice, billed, retry_safe, and next_action. | read-response | Replay the same Idempotency-Key for network uncertainty; do not change the body under the same key. | docs_guides_computed_comprehension |
| Deterministic decline 200 | A computed:false 200 is a successful safety answer, not an outage or a free retry loop. | deterministic-decline-ui | Show code, reason, billed, retry_safe, and next_action; route to review or feedback without a tax estimate. | docs_guides_decline_comprehension |
| needs_review 200 | needs_review is not a final computed tax answer; it is a human-review workflow state. | read-response | Show diff, reason/provenance, billed, retry_safe, and next_action; route to a review queue. | docs_guides_needs_review_comprehension |
| Validation error | A 400 validation failure is unbilled and should be fixed before resubmitting. | billing-retries-quota | Fix the request shape; do not ask support to infer a missing taxpayer fact. | docs_guides_validation_recovery_view |
| Auth error | A 401/403 auth failure is unbilled and usually means the API key or account state needs attention. | billing-retries-quota | Check, rotate, or unsuspend the key; never paste keys or bearer tokens into support or feedback. | docs_guides_auth_recovery_view |
| Quota or rate limit | A 429 is unbilled; monthly quota is a hard cap, while per-minute rate limit can wait/back off. | billing-retries-quota | Wait, back off, or use account/billing support; do not expect silent overage. | docs_guides_quota_recovery_view |
| Idempotency replay | Same-key same-body replay returns the stored result and bills once total. | billing-retries-quota | Reuse the same key for uncertainty about the same logical POST. | docs_guides_replay_comprehension |
| Idempotency mismatch | Same-key different-body mismatch is a client bug, unbilled, and must not be retried with that key. | billing-retries-quota | Use a new key only for a new logical request after fixing the client bug. | docs_guides_mismatch_recovery_view |
| Idempotency in progress | An in-progress response is unbilled at failure time and may be retried with the same key after a short wait. | billing-retries-quota | Retry the same key after the in-flight request settles. | docs_guides_in_progress_recovery_view |
| Server failure | A 500/503 is unbilled and must not produce a guessed tax result in the client UI. | read-response | Retry only when the response class says retry is safe; open support if persistent. | docs_guides_server_failure_recovery_view |
This decline is a successful safety outcome. It has computed:false, a stable code, billed, retry_safe, next_action, and a reason suitable for a review queue. It intentionally has no tax value.
{
"computed": false,
"code": "schedule_c_needs_review",
"reason": "Schedule C self-employment compute requires scheduleCIsSingleSolePropFinalNetAffirmed:true before Tax MCP can compute this bounded path.",
"billed": true,
"retry_safe": false,
"next_action": "review_inputs"
}Privacy-safe guide telemetry may record only named events and coarse categories. It must never include API keys, bearer tokens, taxpayer documents, raw taxpayer PII, full unredacted request/response bodies, or unredacted support text.
| Event | Surface | Purpose | Safe fields |
|---|---|---|---|
docs_guide_index_view | /docs/guides | Detect whether evaluators reach the guide index from docs or quickstart. | session_id, surface, timestamp |
docs_guides_comprehension_map_view | /docs/guides | Detect whether first users see the response-class comprehension map before sending payloads. | session_id, surface, timestamp |
docs_guides_to_quickstart_click | /docs/guides/* | Measure guide-to-first-call continuity without recording request bodies or secrets. | session_id, guide_slug, timestamp |
docs_guides_support_click | /docs/guides/* | Route account or operational confusion to support without collecting raw support text. | session_id, guide_slug, support_category, timestamp |
docs_guides_feedback_click | /docs/guides/* | Route unsupported-envelope surprises to structured feedback without taxpayer PII. | session_id, guide_slug, response_class, decline_or_error_code, timestamp |
docs_guides_privacy_notice_view | /docs/guides/* | Confirm the no-secrets/no-PII support boundary is visible before support or feedback handoff. | session_id, guide_slug, timestamp |
Forbidden fields: api_key, bearer_token, raw_taxpayer_document, raw_taxpayer_pii, full_unredacted_request_body, full_unredacted_response_body, unredacted_free_form_support_text.