---
title: Credito di fallback
url: https://platform.claude.com/docs/it/build-with-claude/fallback-credit
description: Evita di pagare due volte il costo della cache dei prompt quando ritenti su un altro modello una richiesta rifiutata.
---

Le cache dei prompt sono per modello. Quando un modello rifiuta una richiesta e tu ritenti su un altro modello, il prefisso della conversazione già memorizzato nella cache per il primo modello deve essere scritto da zero nella cache del nuovo modello. Le scritture in cache costano più delle letture dalla cache. Il "fallback credit" (credito di fallback) elimina quel costo aggiuntivo. Il rifiuto contiene un token di credito, tu ripeti il token nel nuovo tentativo, e il nuovo tentativo viene fatturato come se la conversazione fosse stata sul nuovo modello fin dall'inizio.

Questa pagina ti serve solo quando costruisci tu stesso il nuovo tentativo: tramite HTTP grezzo o con una logica di retry personalizzata. Il [fallback lato server](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#server-side-fallback) e il [middleware dell'SDK](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#client-side-fallback) applicano il credito di fallback automaticamente. Se usi uno dei due, salta questa pagina.

[Rifiuti e fallback](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback) tratta il rilevamento dei rifiuti e la scelta di un approccio di fallback. [Cache dei prompt](https://platform.claude.com/docs/it/build-with-claude/prompt-caching) spiega le letture dalla cache e le scritture in cache, se questi termini ti sono nuovi.

## Il flusso di base

<Steps>
  <Step title="Attiva la funzionalità con l'header beta">
    Invia la richiesta che potrebbe essere rifiutata con l'header `anthropic-beta: fallback-credit-2026-07-01`. Anche l'header `server-side-fallback-2026-07-01` concede gli stessi campi, tranne su Amazon Bedrock e Google Cloud, che restituiscono un errore 400 per quell'header. Il precedente header `fallback-credit-2026-06-01` rimane accettato e concede gli stessi campi.
  </Step>

  <Step title="Leggi due campi dal rifiuto">
    In caso di rifiuto, `stop_details` include due campi:

    * **`fallback_credit_token`:** una stringa opaca che rappresenta il credito.
    * **`fallback_has_prefill_claim`:** un booleano che ti indica quale forma del corpo del nuovo tentativo usare.

    Entrambi sono `null` quando non è disponibile alcun credito per il rifiuto.
  </Step>

  <Step title="Costruisci il nuovo tentativo">
    Parti dal corpo della richiesta rifiutata. Imposta `model` sul modello di fallback e aggiungi il token come parametro di primo livello `fallback_credit_token`. Scegli la forma del corpo dalla tabella seguente.
  </Step>

  <Step title="Invia il nuovo tentativo con lo stesso header">
    Invia il nuovo tentativo con lo stesso header beta `fallback-credit-2026-07-01`. Il nuovo tentativo ha bisogno dell'header per riscattare il token.
  </Step>
</Steps>

Il campo `fallback_has_prefill_claim` ti indica se il nuovo tentativo può continuare l'output parziale del modello che ha rifiutato invece di ricominciare da capo:

| `fallback_has_prefill_claim` | Corpo del nuovo tentativo                                                                                                                                                                                                                                                                                                                    |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `true`                       | Il corpo della richiesta rifiutata, invariato, più un messaggio assistant aggiunto in coda il cui `content` ripete il `content` della risposta rifiutata. Il modello del nuovo tentativo continua la risposta dal punto in cui il modello che ha rifiutato si è fermato, e le chiamate a strumenti server completate non vengono rieseguite. |
| `false`                      | Il corpo della richiesta rifiutata, invariato.                                                                                                                                                                                                                                                                                               |

## Esempio

L'esempio seguente effettua una richiesta che potrebbe essere rifiutata e riscatta il token di credito in un nuovo tentativo su Claude Opus 4.8. Quando un tentativo viene respinto, l'esempio degrada lungo la scala dei rifiuti: la sequenza di forme di retry progressivamente più semplici trattata in [Quando un nuovo tentativo viene respinto](https://platform.claude.com/docs/it/build-with-claude/fallback-credit#when-a-retry-is-rejected).

<CodeGroup>
  ```bash cURL
  # Richiesta iniziale (potrebbe essere rifiutata)
  response=$(curl --fail-with-body -sS https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: fallback-credit-2026-07-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5",
      "max_tokens": 1024,
      "messages": [{"role": "user", "content": "Hello, Claude"}]
    }')

  # Un rifiuto include un token di credito monouso in stop_details
  token=$(jq -r '.stop_details.fallback_credit_token // empty' <<<"${response}")

  if [[ -n "${token}" ]]; then
    # Riprova sul modello di fallback con il token di credito (stesso corpo)
    response=$(curl --fail-with-body -sS https://api.anthropic.com/v1/messages \
      -H "x-api-key: $ANTHROPIC_API_KEY" \
      -H "anthropic-version: 2023-06-01" \
      -H "anthropic-beta: fallback-credit-2026-07-01" \
      -H "content-type: application/json" \
      -d "$(jq -n --arg token "${token}" '{
        model: "claude-opus-4-8",
        max_tokens: 1024,
        messages: [{"role": "user", "content": "Hello, Claude"}],
        fallback_credit_token: $token
      }')")
  fi

  # Vedi gli esempi dell'SDK per la sequenza completa di gestione dei rifiuti.
  jq -c '{stop_reason, model}' <<<"${response}"
  ```

  ```bash CLI
  # Richiesta iniziale (potrebbe essere rifiutata)
  response=$(ant beta:messages create \
    --model claude-fable-5 \
    --max-tokens 1024 \
    --message '{"role":"user","content":"Hello, Claude"}' \
    --beta fallback-credit-2026-07-01 \
    --format json)

  # Un rifiuto include un token di credito monouso in stop_details
  token=$(jq -r '.stop_details.fallback_credit_token // empty' <<<"${response}")

  if [[ -n "${token}" ]]; then
    # Riprova sul modello di fallback con il token di credito
    response=$(ant beta:messages create \
      --model claude-opus-4-8 \
      --max-tokens 1024 \
      --message '{"role":"user","content":"Hello, Claude"}' \
      --fallback-credit-token "${token}" \
      --beta fallback-credit-2026-07-01 \
      --format json)
  fi

  # Vedi gli esempi dell'SDK per la sequenza completa di gestione dei rifiuti.
  jq -c '{stop_reason, model}' <<<"${response}"
  ```

  ```python Python
  client = Anthropic()

  request = {
      "max_tokens": 1024,
      "messages": [{"role": "user", "content": "Hello, Claude"}],
  }


  def send(model: str, body: dict[str, object]) -> BetaMessage:
      return client.beta.messages.create(
          model=model, betas=["fallback-credit-2026-07-01"], **body
      )


  response = send("claude-fable-5", request)

  if (
      response.stop_reason == "refusal"
      and (details := response.stop_details)
      and (token := details.fallback_credit_token)
  ):
      exact_body = request | {"fallback_credit_token": token}
      # Preferisci la forma di continuazione a meno che il claim non sia False
      if details.fallback_has_prefill_claim is not False:
          echoed = [block.model_dump() for block in response.content]
          match echoed:
              case [*_, {"type": "text"} as final_block]:
                  final_block["text"] = final_block["text"].rstrip()
          attempt = exact_body | {
              "messages": [
                  *request["messages"],
                  {"role": "assistant", "content": echoed},
              ]
          }
      else:
          attempt = exact_body

      try:
          response = send("claude-opus-4-8", attempt)
      except BadRequestError as error:
          if "redemption temporarily unavailable" in error.message:
              raise  # Transient: retry with the token within its five-minute window
          try:
              # Ripiega sul body invariato, sempre con il token
              response = send("claude-opus-4-8", exact_body)
          except BadRequestError as retry_error:
              if "redemption temporarily unavailable" in retry_error.message:
                  raise  # Transient: retry with the token within its five-minute window
              # Il token stesso è stato rifiutato: rinunciavi e riprova senza.
              response = send("claude-opus-4-8", request)

  print(json.dumps({"stop_reason": response.stop_reason, "model": response.model}))
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const request: Anthropic.Beta.MessageCreateParamsNonStreaming = {
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello, Claude" }],
    betas: ["fallback-credit-2026-07-01"]
  };

  let response = await client.beta.messages.create(request);

  if (
    response.stop_reason === "refusal" &&
    response.stop_details?.type === "refusal" &&
    response.stop_details.fallback_credit_token
  ) {
    const { fallback_credit_token, fallback_has_prefill_claim } = response.stop_details;
    const fallbackModel = "claude-opus-4-8";

    const exactRetry: Anthropic.Beta.MessageCreateParamsNonStreaming = {
      ...request,
      model: fallbackModel,
      fallback_credit_token
    };

    // Prima la forma più ricca, degradando a ogni rifiuto: la forma di
    // continuazione (salvo claim falso), il body invariato che porta ancora
    // il token e infine la rinuncia al token.
    let attempt = exactRetry;
    if (fallback_has_prefill_claim !== false) {
      const finalBlock = response.content.at(-1);
      const echoed: Anthropic.Beta.BetaContentBlockParam[] =
        finalBlock?.type === "text"
          ? [
              ...response.content.slice(0, -1),
              { ...finalBlock, text: finalBlock.text.trimEnd() }
            ]
          : response.content;
      attempt = {
        ...exactRetry,
        messages: [...request.messages, { role: "assistant", content: echoed }]
      };
    }

    try {
      response = await client.beta.messages.create(attempt);
    } catch (error) {
      // Degrada solo su un 400 legato alla forma. "redemption temporarily
      // unavailable" è transitorio: riprova allo stesso modo entro la finestra
      // di cinque minuti del token.
      if (
        !(error instanceof Anthropic.BadRequestError) ||
        error.message.includes("redemption temporarily unavailable")
      ) {
        throw error;
      }
      try {
        response = await client.beta.messages.create(exactRetry);
      } catch (retryError) {
        if (
          !(retryError instanceof Anthropic.BadRequestError) ||
          retryError.message.includes("redemption temporarily unavailable")
        ) {
          throw retryError;
        }
        response = await client.beta.messages.create({ ...request, model: fallbackModel });
      }
    }
  }

  const { stop_reason, model } = response;
  console.log(JSON.stringify({ stop_reason, model }));
  ```

  ```csharp C#
  var client = new AnthropicClient();
  const string beta = "fallback-credit-2026-07-01";

  List<BetaMessageParam> requestMessages =
  [
      new() { Role = Role.User, Content = "Hello, Claude" },
  ];
  MessageCreateParams Request(Model model) => new()
  {
      Model = model,
      MaxTokens = 1024,
      Messages = requestMessages,
      Betas = [beta],
  };
  var response = await client.Beta.Messages.Create(Request(Model.ClaudeFable5));

  if (
      response.StopReason == BetaStopReason.Refusal
      && response.StopDetails is { FallbackCreditToken: string token } details
  )
  {
      var exactBody = Request(Model.ClaudeOpus4_8) with { FallbackCreditToken = token };
      var attempt = exactBody;
      // Preferisci la forma di continuazione a meno che l'affermazione sia falsa
      if (details.FallbackHasPrefillClaim is not false)
      {
          var echoed = JsonArray.Create(response.RawData["content"])!;
          if (
              echoed is [.., JsonObject lastBlock]
              && lastBlock["type"]?.GetValue<string>() is "text"
              && lastBlock["text"]?.GetValue<string>() is string text
          )
          {
              lastBlock["text"] = text.TrimEnd();
          }
          attempt = exactBody with
          {
              Messages =
              [
                  .. requestMessages,
                  new()
                  {
                      Role = Role.Assistant,
                      Content = new BetaMessageParamContent(
                          JsonSerializer.SerializeToElement(echoed)
                      ),
                  },
              ],
          };
      }
      // Un rifiuto transitorio "redemption temporarily unavailable" si propaga fuori da
      // ciascuno dei seguenti filtri catch: riprova con il token entro la sua finestra di cinque minuti.
      try
      {
          response = await client.Beta.Messages.Create(attempt);
      }
      catch (AnthropicBadRequestException e)
          when (!e.Message.Contains("redemption temporarily unavailable"))
      {
          try
          {
              // Ripiega sul corpo invariato, sempre con il token
              response = await client.Beta.Messages.Create(exactBody);
          }
          catch (AnthropicBadRequestException retryError)
              when (!retryError.Message.Contains("redemption temporarily unavailable"))
          {
              // Il token stesso è stato rifiutato: rinunciavi e riprova senza.
              response = await client.Beta.Messages.Create(Request(Model.ClaudeOpus4_8));
          }
      }
  }

  Console.WriteLine(
      JsonSerializer.Serialize(
          new { stop_reason = response.StopReason?.Raw(), model = response.Model.Raw() }
      )
  );
  ```

  ```go Go
  ctx := context.Background()
  client := anthropic.NewClient()

  request := anthropic.BetaMessageNewParams{
  	MaxTokens: 1024,
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaFallbackCredit2026_07_01},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  	},
  }

  send := func(model anthropic.Model, body anthropic.BetaMessageNewParams) (*anthropic.BetaMessage, error) {
  	body.Model = model
  	return client.Beta.Messages.New(ctx, body)
  }
  // Un 400 non transitorio indica che questa forma di tentativo o token è stata rifiutata e
  // che deve essere eseguito il gradino successivo della scala. "redemption temporarily
  // unavailable" è transitorio: segnalalo e riprova con il token entro
  // la sua finestra di cinque minuti.
  canFallBack := func(err error) bool {
  	apiErr, ok := errors.AsType[*anthropic.Error](err)
  	return ok && apiErr.StatusCode == 400 &&
  		!strings.Contains(apiErr.Error(), "redemption temporarily unavailable")
  }

  response, err := send(anthropic.ModelClaudeFable5, request)
  if err != nil {
  	log.Fatal(err)
  }

  if response.StopReason == anthropic.BetaStopReasonRefusal {
  	details := response.StopDetails
  	if token := details.FallbackCreditToken; token != "" {
  		exactBody := request
  		exactBody.FallbackCreditToken = anthropic.BetaMessageNewParamsFallbackCreditTokenUnion{
  			OfString: anthropic.String(token),
  		}
  		attempt := exactBody
  		// Preferisci la forma di continuazione a meno che il claim non sia false
  		if details.FallbackHasPrefillClaim || !details.JSON.FallbackHasPrefillClaim.Valid() {
  			echoed := response.ToParam()
  			if len(echoed.Content) > 0 {
  				if text := echoed.Content[len(echoed.Content)-1].OfText; text != nil {
  					text.Text = strings.TrimRightFunc(text.Text, unicode.IsSpace)
  				}
  			}
  			attempt.Messages = append(slices.Clone(request.Messages), echoed)
  		}
  		response, err = send(anthropic.ModelClaudeOpus4_8, attempt)
  		if err != nil && canFallBack(err) {
  			// Ripiega sul body invariato, sempre con il token
  			response, err = send(anthropic.ModelClaudeOpus4_8, exactBody)
  			if err != nil && canFallBack(err) {
  				// Il token stesso è stato rifiutato: rinunciavi e riprova senza.
  				response, err = send(anthropic.ModelClaudeOpus4_8, request)
  			}
  		}
  		if err != nil {
  			log.Fatal(err)
  		}
  	}
  }

  summary, err := json.Marshal(struct {
  	StopReason anthropic.BetaStopReason `json:"stop_reason"`
  	Model      anthropic.Model          `json:"model"`
  }{response.StopReason, response.Model})
  if err != nil {
  	log.Fatal(err)
  }
  fmt.Println(string(summary))
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  MessageCreateParams.Builder request() {
      return MessageCreateParams.builder()
          .maxTokens(1024L)
          .addUserMessage("Hello, Claude")
          .addBeta(AnthropicBeta.FALLBACK_CREDIT_2026_07_01);
  }

  BetaMessage send(Model model, MessageCreateParams.Builder body) {
      return client.beta().messages().create(body.model(model).build());
  }

  void main() {
      BetaMessage response = send(Model.CLAUDE_FABLE_5, request());

      if (response.stopReason().map(BetaStopReason.REFUSAL::equals).orElse(false)
              && response.stopDetails().orElse(null) instanceof BetaRefusalStopDetails details
              && details.fallbackCreditToken().orElse(null) instanceof String creditToken) {
          MessageCreateParams.Builder attempt = request().fallbackCreditToken(creditToken);
          // Preferisci la forma di continuazione a meno che l'affermazione sia falsa
          if (details.fallbackHasPrefillClaim().orElse(true)) {
              List<BetaContentBlockParam> echoed = new ArrayList<>(
                  response.content().stream().map(BetaContentBlock::toParam).toList());
              if (!echoed.isEmpty() && echoed.getLast().isText()) {
                  var lastText = echoed.removeLast().asText();
                  echoed.addLast(BetaContentBlockParam.ofText(
                      lastText.toBuilder().text(lastText.text().stripTrailing()).build()));
              }
              attempt.addAssistantMessageOfBetaContentBlockParams(echoed);
          }
          try {
              response = send(Model.CLAUDE_OPUS_4_8, attempt);
          } catch (BadRequestException badRequest) {
              // Transitorio: riprova con il token entro la sua finestra di cinque minuti
              if (badRequest.getMessage().contains("redemption temporarily unavailable")) {
                  throw badRequest;
              }
              try {
                  // Ripiega sul body invariato, sempre con il token
                  response = send(Model.CLAUDE_OPUS_4_8, request().fallbackCreditToken(creditToken));
              } catch (BadRequestException retryBadRequest) {
                  if (retryBadRequest.getMessage().contains("redemption temporarily unavailable")) {
                      throw retryBadRequest;
                  }
                  // Il token stesso è stato rifiutato: rinunciaci e riprova senza.
                  response = send(Model.CLAUDE_OPUS_4_8, request());
              }
          }
      }

      IO.println("""
          {"stop_reason": "%s", "model": "%s"}"""
          .formatted(response.stopReason().orElseThrow(), response.model()));
  }
  ```

  ```php PHP
  $client = new Client();
  $beta = 'fallback-credit-2026-07-01';
  $messages = [['role' => 'user', 'content' => 'Hello, Claude']];

  $send = fn (string $model, array $messages, ?string $token = null) => $client->beta->messages->create(
      maxTokens: 1024,
      messages: $messages,
      model: $model,
      fallbackCreditToken: $token,
      betas: [$beta],
  );
  $response = $send('claude-fable-5', $messages);

  $token = $response->stopReason === 'refusal'
      ? $response->stopDetails?->fallbackCreditToken
      : null;

  if ($token !== null) {
      $attemptMessages = $messages;
      // Preferisci la forma di continuazione a meno che l'affermazione sia falsa
      if ($response->stopDetails->fallbackHasPrefillClaim !== false) {
          $echoed = $response->content
              |> json_encode(...)
              |> (fn (string $json): array => json_decode($json, associative: true));
          $lastIndex = array_key_last($echoed);
          if ($lastIndex !== null && $echoed[$lastIndex]['type'] === 'text') {
              $echoed[$lastIndex]['text'] = rtrim($echoed[$lastIndex]['text']);
          }
          $attemptMessages[] = ['role' => 'assistant', 'content' => $echoed];
      }
      // Transitorio: riprova con il token entro la sua finestra di cinque minuti
      $isTransientRedemption = fn (BadRequestException $error): bool =>
          str_contains($error->getMessage(), 'redemption temporarily unavailable');
      try {
          $response = $send('claude-opus-4-8', $attemptMessages, $token);
      } catch (BadRequestException $error) {
          if ($isTransientRedemption($error)) {
              throw $error;
          }
          try {
              // Ripiega sul corpo invariato, sempre con il token
              $response = $send('claude-opus-4-8', $messages, $token);
          } catch (BadRequestException $retryError) {
              if ($isTransientRedemption($retryError)) {
                  throw $retryError;
              }
              // Il token stesso è stato rifiutato: rinunciavi e riprova senza.
              $response = $send('claude-opus-4-8', $messages);
          }
      }
  }

  echo json_encode(['stop_reason' => $response->stopReason, 'model' => $response->model]), PHP_EOL;
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  request = {
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}]
  }

  send_message = ->(model, body) do
    client.beta.messages.create(model:, betas: ["fallback-credit-2026-07-01"], **body)
  end

  response = send_message.call("claude-fable-5", request)

  if response in {stop_reason: :refusal,
                  stop_details: {fallback_credit_token: String => credit_token} => details}
    exact_body = request.merge(fallback_credit_token: credit_token)

    # Preferisci la forma di continuazione a meno che l'affermazione sia falsa
    attempt = if details.fallback_has_prefill_claim != false
      echoed = response.content.map(&:to_h)
      if echoed.last in {type: :text, text: String => final_text}
        echoed[-1] = echoed.last.merge(text: final_text.rstrip)
      end
      exact_body.merge(
        messages: [*request[:messages], {role: "assistant", content: echoed}]
      )
    else
      exact_body
    end

    begin
      response = send_message.call("claude-opus-4-8", attempt)
    rescue Anthropic::Errors::BadRequestError => error
      # Transitorio: riprova con il token entro la sua finestra di cinque minuti
      raise if error.message.include?("redemption temporarily unavailable")
      begin
        # Ripiega sul body invariato, sempre con il token
        response = send_message.call("claude-opus-4-8", exact_body)
      rescue Anthropic::Errors::BadRequestError => error
        # Transitorio: riprova con il token entro la sua finestra di cinque minuti
        raise if error.message.include?("redemption temporarily unavailable")
        # Il token stesso è stato rifiutato: rinunciavi e riprova senza.
        response = send_message.call("claude-opus-4-8", request)
      end
    end
  end

  puts JSON.generate({stop_reason: response.stop_reason, model: response.model})
  ```
</CodeGroup>

## Dove funziona

Il credito di fallback è in beta sulla Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud e Microsoft Foundry. I rifiuti nei [Message Batches](https://platform.claude.com/docs/it/build-with-claude/batch-processing) non generano token di credito, e il riscatto si applica solo alle richieste dirette alla Messages API: un token passato in una richiesta batch viene accettato ma ignorato. Un rifiuto di Claude Haiku 5.5 non include alcun credito di fallback, quindi un nuovo tentativo successivo paga il costo completo della scrittura della cache dei prompt del modello di fallback.

Il modello del nuovo tentativo deve essere uno dei target di fallback consentiti per il modello che ha rifiutato. Per Claude Fable 5.1, Claude Fable 5 e Claude Opus 5.5, questi sono Claude Opus 4.8 (`claude-opus-4-8`) e Claude Opus 5 (`claude-opus-5`). Per Claude Opus 5, è Claude Opus 4.8. Per Claude Sonnet 5.5, è Claude Sonnet 5 (`claude-sonnet-5`).

<Accordion title="Cercare i target di fallback consentiti in modo programmatico">
  Sulla Claude API e su Claude Platform su AWS, l'elenco dei target è pubblicato come `allowed_fallback_models` nella voce di ciascun modello nella [Models API](https://platform.claude.com/docs/it/api/models/list) quando è impostato l'header beta `server-side-fallback-2026-07-01`. L'elenco non è ancora visibile con il solo header `fallback-credit-*`. Non è esposto su Amazon Bedrock, Google Cloud o Microsoft Foundry.
</Accordion>

## Verificare che il credito sia stato applicato

Il rimborso è visibile nello `usage` del nuovo tentativo. Rispetto a quanto la stessa richiesta riporterebbe senza il token, `cache_creation_input_tokens` è più basso e `cache_read_input_tokens` è più alto della stessa quantità. Uno scostamento pari a zero significa che il token è stato onorato ma non c'era nulla da riprezzare, ad esempio perché la cache del modello del nuovo tentativo era già calda.

## Quando un nuovo tentativo viene respinto

La maggior parte dei nuovi tentativi riscatta il credito al primo colpo. Quando ciò non accade, l'API restituisce un errore 400 che ti indica cosa provare dopo.

<Steps>
  <Step title="Continuazione respinta: reinvia il corpo invariato">
    Se il nuovo tentativo che aggiunge il messaggio assistant viene respinto con un errore 400, reinvia il corpo della richiesta rifiutata invariato, sempre con il token.
  </Step>

  <Step title="Token respinto: elimina il token">
    Se anche il corpo invariato viene respinto con un errore 400 il cui messaggio cita `fallback_credit_token`, ritenta senza il token. Il credito viene perso, ma il nuovo tentativo in sé va a buon fine.
  </Step>
</Steps>

<Note>
  Se la richiesta rifiutata ha eseguito strumenti server, un nuovo tentativo senza token riesegue e rifattura quegli strumenti. In quel caso, esponi l'errore 400 al tuo chiamante invece di ricadere su un nuovo tentativo senza token.
</Note>

<Accordion title="Se l'errore dice 'redemption temporarily unavailable'">
  Questo rifiuto è transitorio, non un verdetto sulla forma del tuo nuovo tentativo. Ritenta la stessa richiesta, con lo stesso token, entro la finestra di cinque minuti del token. Non passare al gradino successivo della scala.
</Accordion>

## Riferimento

Le sezioni seguenti trattano i casi limite e le regole complete di riscatto. La maggior parte delle integrazioni non ne ha bisogno.

<Accordion title="Campi che devono corrispondere alla richiesta rifiutata">
  Il riscatto confronta il nuovo tentativo con la richiesta rifiutata. Ogni campo che dà forma al prompt deve corrispondere esattamente. I campi che non danno forma al prompt possono cambiare nel nuovo tentativo.

  | Regola                               | Campi                                                                                                                                                            |
  | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | Devono corrispondere esattamente     | `system`, `messages`, `tools`, `tool_choice`, `thinking` e `cache_control`, più `output_config`, `mcp_servers`, `context_management` e `container` quando li usi |
  | Possono cambiare nel nuovo tentativo | `model`, `max_tokens`, `stop_sequences`, `temperature`, `top_p`, `top_k`, `stream`, `metadata` e `service_tier`                                                  |

  La forma di continuazione (`fallback_has_prefill_claim: true`) è l'unica eccezione alla corrispondenza di `messages`: aggiunge esattamente un messaggio assistant alla fine di `messages`.

  Non rimuovere i blocchi `thinking` o `redacted_thinking` dai turni precedenti nel nuovo tentativo, anche se un normale retry senza token di solito li rimuove. Il corpo deve corrispondere alla richiesta rifiutata, e il server gestisce quei blocchi da sé.
</Accordion>

<Accordion title="Anche gli header beta devono corrispondere">
  Invia nel nuovo tentativo gli stessi header `anthropic-beta` della richiesta rifiutata. Un header beta presente in una delle due richieste ma non nell'altra può far fallire la corrispondenza anche quando i corpi sono identici. L'errore 400 risultante riporta lo stesso messaggio `request body ... does not match` di una differenza nel corpo, quindi è facile scambiare una differenza negli header per un problema del corpo. In particolare, non aggiungere né rimuovere header beta in base al modello a cui è destinata la richiesta.

  Due famiglie di header sono esenti dalla corrispondenza, a beneficio del nuovo tentativo:

  * **`server-side-fallback-*`:** un nuovo tentativo deve eliminare il parametro `fallbacks`, ed eliminare questo header insieme ad esso non causa una mancata corrispondenza.
  * **`fallback-credit-*`:** mantieni questo header in entrambe le richieste. Il nuovo tentativo ne ha bisogno per riscattare il token.

  <Note>
    Sui modelli che includono per impostazione predefinita la finestra di contesto da 1M token, come Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Sonnet 5.5 e Claude Sonnet 5, l'header beta `context-1m-2025-08-07` non ha alcun effetto. Per mantenere identiche le due richieste, ometti quell'header in entrambe invece di inviarlo in una e non nell'altra.
  </Note>
</Accordion>

<Accordion title="Quando fallback_has_prefill_claim è assente">
  Il campo non ha valore solo quando non ce l'ha nemmeno il token, quindi finché possiedi un token il campo ha un valore, tranne su Amazon Bedrock, Google Cloud e Microsoft Foundry, dove può ancora essere assente mentre il supporto per il campo viene distribuito. In tal caso, considera la forma del nuovo tentativo come sconosciuta anziché come `false` (python: `False`). Prova prima la forma con il messaggio assistant aggiunto e affidati alla gestione dei rifiuti descritta in [Quando un nuovo tentativo viene respinto](https://platform.claude.com/docs/it/build-with-claude/fallback-credit#when-a-retry-is-rejected), che ripiega sul corpo invariato.
</Accordion>

<Accordion title="Ripetere il content della risposta rifiutata">
  Quando il token di un rifiuto supporta la forma di continuazione, il `content` della risposta contiene solo l'output del modello stesso, e la spiegazione del rifiuto viene fornita in `stop_details.explanation`. Puoi quindi ripetere `content` nel messaggio assistant aggiunto così com'è.

  Potrebbero comunque essere necessari due aggiustamenti prima dell'invio:

  * Se il blocco finale che invii è un blocco `text`, rimuovi i suoi spazi bianchi finali.
  * Ometti qualsiasi blocco `tool_use` lato client che non abbia un `tool_result` corrispondente.

  Se il contenuto ripetuto include un blocco `fallback` proveniente da un precedente [fallback lato server](https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback#server-side-fallback), mantieni il blocco esattamente dove appariva. È accettato in qualsiasi richiesta senza un header beta. L'API usa la sua posizione per validare i blocchi thinking intorno ad esso, quindi una richiesta che ripete blocchi thinking da entrambi i lati di quel confine viene respinta se il blocco viene omesso o spostato.
</Accordion>

<Accordion title="Ambito e durata del token">
  Il token si riscatta solo dall'organizzazione e dal workspace che hanno ricevuto il rifiuto, anche su Microsoft Foundry. Su Amazon Bedrock e Google Cloud, che non hanno workspace, il token è invece legato all'identità del chiamante della piattaforma.

  Il token scade cinque minuti dopo il rifiuto. Dopo di che, invia il nuovo tentativo senza di esso. Il token è inoltre stateless: il server non memorizza nulla al riguardo, e non esiste alcun endpoint per ispezionarlo o revocarlo.
</Accordion>

<Accordion title="Quando un token non può essere riscattato con nessuna delle due forme">
  Quando il rifiuto è arrivato dopo che gli strumenti server erano già stati eseguiti all'interno della richiesta, il token si riscatta solo continuando la risposta parziale. Questa restrizione è ciò che impedisce alle chiamate a strumenti completate di essere eseguite, e fatturate, di nuovo.

  Una combinazione può quindi lasciare il token non riscattabile con nessuna delle due forme, quando entrambe le seguenti condizioni sono vere:

  * La richiesta usava `output_config.format` o un `tool_choice` che forza l'uso degli strumenti. Ciascuno dei due esclude la forma con il messaggio assistant aggiunto.
  * Il rifiuto è arrivato dopo che gli strumenti server erano stati eseguiti. Questo esclude il corpo invariato.

  Se il nuovo tentativo con corpo invariato viene respinto con un errore 400 che dice che il token deve essere riscattato continuando la risposta parziale, scarta il token. Un nuovo tentativo senza di esso va a buon fine, ma riesegue e rifattura gli strumenti server completati. Esponi il costo o l'errore al tuo chiamante invece di ritentare silenziosamente.
</Accordion>

## Prossimi passi

<CardGroup>
  <Card title="Rifiuti e fallback" icon="shield" href="https://platform.claude.com/docs/it/build-with-claude/refusals-and-fallback">
    Rileva i rifiuti e scegli tra fallback lato server, middleware dell'SDK e nuovo tentativo manuale.
  </Card>

  <Card title="Cache dei prompt" icon="bolt" href="https://platform.claude.com/docs/it/build-with-claude/prompt-caching">
    Come vengono fatturate le letture dalla cache e le scritture in cache.
  </Card>

  <Card title="Motivi di arresto e fallback" icon="code" href="https://platform.claude.com/docs/it/build-with-claude/handling-stop-reasons">
    Ogni valore di `stop_reason` e come gestirlo.
  </Card>

  <Card title="Middleware dell'SDK" icon="settings" href="https://platform.claude.com/docs/it/cli-sdks-libraries/middleware">
    L'helper dell'SDK che applica il credito di fallback automaticamente.
  </Card>
</CardGroup>
