> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fiveninelabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# declined_to_spend

> We refused to spend your money on this query — a $0 abstained run, stated, with would_run:false on the free estimate as the pre-spend signal.

**Reserved code — not emitted today.** Before any money moves, the parse decides
whether spending on this query could honestly deliver. When the answer is no —
there's no purchasable entity, the ask isn't catalog-shaped, the constraints can't be
shopped — the API declines to spend. **How that reaches you is not an HTTP error**:

1. **Before you commit (the gate to build on):** `POST /v1/sessions/estimate` returns
   `would_run: false` with the parsed intent, what's `missing`, and the reason —
   free, at \$0, always callable. Validate user-supplied queries here before offering
   to run them.
2. **If you create anyway:** `POST /v1/sessions` returns **`201`** with a running
   session and a reservation, and within seconds the run ends with an `abstain`
   event (`reason` attached) → status **`abstained`**, **\$0 settled**, the
   reservation released in full. Nothing was dispatched; the parse's reasoning is in
   the event log.

This is the abstain posture end to end: a stated \$0 outcome, not a failure dressed up
as an empty result — and not a synchronous error your create call must catch.

## The shapes to program against

The estimate, declining (\$0, before any session exists):

```json theme={null}
{
  "would_run": false,
  "parsed": { "geo": "Austin, TX", "confidence": "0.05" },
  "planned_merchants": [],
  "planned_dispatches": 0
}
```

The run ending, if you create anyway (`201`, then on the stream):

```json theme={null}
{ "phase": "abstain", "reason": "the intent is too thin to spend a query budget on" }
```

…and the session settles as `"status": "abstained"`, `"spend_usd": 0`.

<Note>
  An earlier draft of this contract described a synchronous **`422 declined_to_spend`**
  at `POST /v1/sessions`. The live API does not emit it — clients must not gate on a
  422, and error-handling code keyed to this HTTP code is dead code today. The code
  stays reserved in the catalog (open enum); if a synchronous decline ever ships it
  will be a dated-version change announced in the [changelog](/changelog).
</Note>

## How to fix a decline

* Read the estimate's `parsed`/`missing` against your intent. The common fixes: name
  a concrete entity ("vinyl records", "espresso machines", not "something nice"), and
  phrase a shopping question rather than a general-knowledge one.
* Gate on `would_run` — it's free and it's the same parse the create uses.
* If you know the exact catalog URL, the question-free path is
  [extractions](/guides/extractions) (planned — not yet available).
* If you believe the decline is wrong, include the `fn-request-id` (estimate) or the
  session id (abstained run) in a support message — both join to our logs.

## Reproduce it

Deterministic on an `fn_test_` key with the
[`FN_TEST_DECLINE` sentinel](/guides/test-mode) — a `201` create whose run streams
the `abstain` and ends `abstained` at \$0, exactly like production:

```bash theme={null}
curl -N https://api.fiveninelabs.com/v1/sessions \
  -H "Authorization: Bearer $FIVENINE_TEST_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"query": "FN_TEST_DECLINE anything at all", "max_spend_usd": 1}'
```

And rehearse the pre-spend gate with the same sentinel on the estimate:
`POST /v1/sessions/estimate {"query": "FN_TEST_DECLINE …"}` → `would_run: false`.
