fallback-credit changedbuild-with-claude/fallback-credit
Nearest release: v2.1.307, published an hour after this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Recorded here
Lines+18added
Lines−18removed
From line
4
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits14to this page, all time
The whole hunk
from line 4, old and new numbered
/
from line 4
44description: Avoid paying the prompt-cache cost twice when you retry a refused request on another model.
55---
66
7Prompt caches are per-model. When a model declines a request and you retry on another model, the conversation prefix already cached for the first model must be written into the new model's cache from scratch. Cache writes cost more than cache reads. Fallback credit removes that extra cost. The refusal carries a credit token, you echo the token on the retry, and the retry is billed as though the conversation had been on the new model all along.
7Prompt caches are per-model. When a model declines a request and you retry on another model, the conversation prefix already cached for the first model must be written into the new model's cache in full. Cache writes cost more than cache reads. Fallback credit removes that extra cost. The refusal carries a credit token, you echo the token on the retry, and the retry is billed as though the conversation had been on the new model from the start.
88
99You need this page only when you build the retry yourself: over raw HTTP or with custom retry logic. [Server-side fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#server-side-fallback) and the [SDK middleware](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#client-side-fallback) apply fallback credit automatically. If you use either, skip this page.
1010
from line 20
2020 <Step title="Read two fields from the refusal">
2121 On a refusal, `stop_details` includes two fields:
2222
23 * **`fallback_credit_token`:** an opaque string that represents the credit.
24 * **`fallback_has_prefill_claim`:** a Boolean that tells you which retry body shape to use.
23 * **`fallback_credit_token`:** an opaque string that represents the credit
24 * **`fallback_has_prefill_claim`:** a Boolean that tells you which retry body shape to use
2525
2626 Both are `null` when no credit is available for the refusal.
2727 </Step>
from line 37
3737
3838The `fallback_has_prefill_claim` field tells you whether the retry can continue the refused model's partial output instead of starting over:
3939
40| `fallback_has_prefill_claim` | Retry body |
41| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42| `true` | The refused request body, unchanged, plus one appended assistant message whose `content` echoes the refused response's `content`. The retry model continues the response from where the refused model stopped, and completed server tool calls are not re-executed. |
43| `false` | The refused request body, unchanged. |
40| `fallback_has_prefill_claim` | Retry body |
41| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42| `true` | The refused request body, unchanged, plus one appended assistant message whose `content` echoes the refused response's `content`. The retry model continues the response from where the refused model stopped, and completed server tool calls are not run again. |
43| `false` | The refused request body, unchanged. |
4444
4545## Example
4646
47The following example makes a request that may be refused and redeems the credit token on a retry against Claude Opus 4.8. When a retry attempt is rejected, the example degrades through the rejection ladder: the sequence of progressively simpler retry shapes covered in [When a retry is rejected](https://platform.claude.com/docs/en/build-with-claude/fallback-credit#when-a-retry-is-rejected).
47The following example makes a request that might be refused and redeems the credit token on a retry against Claude Opus 4.8. When a retry attempt is rejected, the example degrades through the rejection ladder: the sequence of progressively simpler retry shapes covered in [When a retry is rejected](https://platform.claude.com/docs/en/build-with-claude/fallback-credit#when-a-retry-is-rejected).
4848
4949<CodeGroup exclude="shell:cURL, shell:CLI">
5050 <CodeGroupItem language="cURL">
from line 462
462462 client.beta.messages.create(model:, betas: ["fallback-credit-2026-07-01"], **body)
463463 end
464464
465 response = send_message.call("claude-fable-5", request)
465 response = send_message.call(Anthropic::Model::CLAUDE_FABLE_5, request)
466466
467467 if response in {stop_reason: :refusal,
468468 stop_details: {fallback_credit_token: String => credit_token} => details}
from line 482
482482 end
483483
484484 begin
485 response = send_message.call("claude-opus-4-8", attempt)
485 response = send_message.call(Anthropic::Model::CLAUDE_OPUS_4_8, attempt)
486486 rescue Anthropic::Errors::BadRequestError => error
487487 # Transient: retry with the token within its five-minute window
488488 raise if error.message.include?("redemption temporarily unavailable")
489489 begin
490490 # Fall back to the unchanged body, still with the token
491 response = send_message.call("claude-opus-4-8", exact_body)
491 response = send_message.call(Anthropic::Model::CLAUDE_OPUS_4_8, exact_body)
492492 rescue Anthropic::Errors::BadRequestError => error
493493 # Transient: retry with the token within its five-minute window
494494 raise if error.message.include?("redemption temporarily unavailable")
495495 # The token itself was rejected: forfeit it and retry without.
496 response = send_message.call("claude-opus-4-8", request)
496 response = send_message.call(Anthropic::Model::CLAUDE_OPUS_4_8, request)
497497 end
498498 end
499499 end
from line 531
531531</Steps>
532532
533533<Note>
534 If the refused request executed server tools, a tokenless retry re-runs and re-bills those tools. In that case, surface the 400 error to your caller instead of falling through to a tokenless retry.
534 If the refused request ran server tools, a tokenless retry re-runs and re-bills those tools. In that case, surface the 400 error to your caller instead of falling through to a tokenless retry.
535535</Note>
536536
537537<Accordion title="If the error says 'redemption temporarily unavailable'">
538 This rejection is transient, not a verdict on your retry shape. Retry the same request, with the same token, within the token's five-minute window. Do not move to the next step of the ladder.
538 This rejection is transient, not a verdict on your retry shape. Retry the same request, with the same token, within the token's 5-minute window. Do not move to the next step of the ladder.
539539</Accordion>
540540
541541## Reference
from line 575
575575<Accordion title="Echoing the refused response's content">
576576 When a refusal's token supports the continuation shape, the response `content` carries only the model's own output, and the refusal explanation is delivered in `stop_details.explanation`. You can therefore echo `content` into the appended assistant message as-is.
577577
578 Two adjustments may still be needed before sending:
578 Two adjustments might still be needed before sending:
579579
580580 * If the final block you send is a `text` block, strip its trailing whitespace.
581581 * Omit any client-side `tool_use` block that has no matching `tool_result`.
from line 586
586586<Accordion title="Token scope and lifetime">
587587 The token redeems only from the organization and workspace that received the refusal, including on Microsoft Foundry. On Amazon Bedrock and Google Cloud, which do not have workspaces, the token is bound to the platform's caller identity instead.
588588
589 The token expires five minutes after the refusal. After that, send the retry without it. The token is also stateless: the server stores nothing about it, and there is no endpoint to inspect or revoke it.
589 The token expires 5 minutes after the refusal. After that, send the retry without it. The token is also stateless: the server stores nothing about it, and there is no endpoint to inspect or revoke it.
590590</Accordion>
591591
592592<Accordion title="When a token cannot be redeemed by either shape">
593 When the refusal arrived after server tools had already executed within the request, the token redeems only by continuing the partial response. That restriction is what prevents the completed tool calls from running, and billing, again.
593 When the refusal arrived after server tools had already run within the request, the token redeems only by continuing the partial response. That restriction is what prevents the completed tool calls from running, and billing, again.
594594
595595 One combination can therefore leave the token unredeemable by either shape, when both of the following are true:
596596
597597 * The request used `output_config.format` or a `tool_choice` that forces tool use. Either one rules out the appended-assistant-message shape.
598 * The refusal arrived after server tools had executed. That rules out the unchanged body.
598 * The refusal arrived after server tools had run. That rules out the unchanged body.
599599
600600 If the unchanged-body retry is rejected with a 400 error saying the token must be redeemed by continuing the partial response, discard the token. A retry without it goes through, but it re-runs and re-bills the completed server tools. Surface the cost or the error to your caller rather than retrying silently.
601601</Accordion>
No line in this hunk matches that.