---
title: 備援抵免
url: https://platform.claude.com/docs/zh-TW/build-with-claude/fallback-credit
description: 當您在另一個模型上重試被拒絕的請求時，避免重複支付提示快取的費用。
---

提示快取是依模型區分的。當某個模型拒絕一個請求，而您在另一個模型上重試時，已為第一個模型快取的對話前綴必須從頭寫入新模型的快取。快取寫入的費用高於快取讀取。「Fallback credit」（備援抵免）可消除這筆額外費用。拒絕回應會附帶一個抵免權杖，您在重試時回傳該權杖，重試便會以彷彿對話一直都在新模型上進行的方式計費。

只有當您自行建構重試時才需要閱讀本頁：透過原始 HTTP 或使用自訂重試邏輯。[伺服器端備援](https://platform.claude.com/docs/zh-TW/build-with-claude/refusals-and-fallback#server-side-fallback)與 [SDK 中介軟體](https://platform.claude.com/docs/zh-TW/build-with-claude/refusals-and-fallback#client-side-fallback)會自動套用備援抵免。如果您使用其中任一種，請跳過本頁。

[拒絕與備援](https://platform.claude.com/docs/zh-TW/build-with-claude/refusals-and-fallback)涵蓋如何偵測拒絕以及選擇備援方式。若您對快取讀取與快取寫入這些術語感到陌生，[提示快取](https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching)有相關說明。

## 基本流程

<Steps>
  <Step title="使用 beta 標頭選擇加入">
    傳送可能被拒絕的請求時，附上 `anthropic-beta: fallback-credit-2026-07-01` 標頭。`server-side-fallback-2026-07-01` 標頭也會提供相同的欄位，但 Amazon Bedrock 和 Google Cloud 除外，這兩者會對該標頭回傳 400 錯誤。較早的 `fallback-credit-2026-06-01` 標頭仍然可用，並提供相同的欄位。
  </Step>

  <Step title="從拒絕回應中讀取兩個欄位">
    發生拒絕時，`stop_details` 包含兩個欄位：

    * **`fallback_credit_token`：** 代表抵免的不透明字串。
    * **`fallback_has_prefill_claim`：** 一個布林值，告訴您應使用哪種重試主體形式。

    當該拒絕沒有可用的抵免時，兩者皆為 `null`。
  </Step>

  <Step title="建構重試">
    從被拒絕的請求主體開始。將 `model` 設為備援模型，並將權杖加入為頂層的 `fallback_credit_token` 參數。從下表中選擇主體形式。
  </Step>

  <Step title="使用相同的標頭傳送重試">
    使用相同的 `fallback-credit-2026-07-01` beta 標頭傳送重試。重試需要該標頭才能兌換權杖。
  </Step>
</Steps>

`fallback_has_prefill_claim` 欄位告訴您重試是否可以接續被拒絕模型的部分輸出，而非從頭開始：

| `fallback_has_prefill_claim` | 重試主體                                                                                                    |
| ---------------------------- | ------------------------------------------------------------------------------------------------------- |
| `true`                       | 被拒絕的請求主體（不變），再附加一則 assistant 訊息，其 `content` 回傳被拒絕回應的 `content`。重試模型會從被拒絕模型停止的地方接續回應，且已完成的伺服器工具呼叫不會重新執行。 |
| `false`                      | 被拒絕的請求主體（不變）。                                                                                           |

## 範例

以下範例發出一個可能被拒絕的請求，並在針對 Claude Opus 4.8 的重試中兌換抵免權杖。當某次重試嘗試被拒絕時，範例會沿著拒絕階梯逐步降級：也就是[當重試被拒絕時](https://platform.claude.com/docs/zh-TW/build-with-claude/fallback-credit#when-a-retry-is-rejected)中所涵蓋的一系列逐漸簡化的重試形式。

<CodeGroup>
  ```bash cURL
  # 初始請求（可能會被拒絕）
  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"}]
    }')

  # 拒絕回應會在 stop_details 中附帶一次性的 credit token
  token=$(jq -r '.stop_details.fallback_credit_token // empty' <<<"${response}")

  if [[ -n "${token}" ]]; then
    # 使用 credit token 在備援模型上重試（相同的請求主體）
    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

  # 完整的拒絕處理流程請參閱 SDK 範例。
  jq -c '{stop_reason, model}' <<<"${response}"
  ```

  ```bash CLI
  # 初始請求（可能會被拒絕）
  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)

  # 拒絕回應會在 stop_details 中附帶一次性的 credit token
  token=$(jq -r '.stop_details.fallback_credit_token // empty' <<<"${response}")

  if [[ -n "${token}" ]]; then
    # 使用 credit token 在備援模型上重試
    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

  # 完整的拒絕處理流程請參閱 SDK 範例。
  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}
      # 除非 claim 為 False，否則優先採用 continuation 形式
      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:
              # 退回使用未變更的 body，仍附帶 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
              # token 本身遭拒：放棄該 token 並在不帶 token 的情況下重試。
              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
    };

    // 先嘗試最豐富的形式，每次遭拒後逐步降級：延續
    // 形式（除非該宣告為假）、仍攜帶
    // token 的未變更主體，最後則放棄該 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) {
      // 僅在與形式相關的 400 錯誤時降級。「redemption temporarily
      // unavailable」屬暫時性錯誤：應改為在 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;
      // 除非該宣告為 false，否則優先採用 continuation 形式
      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)
                      ),
                  },
              ],
          };
      }
      // 暫時性的「兌換暫時無法使用」拒絕會從以下每個
      // catch 篩選器中向外傳播：在其五分鐘的時效內使用該 token 重試。
      try
      {
          response = await client.Beta.Messages.Create(attempt);
      }
      catch (AnthropicBadRequestException e)
          when (!e.Message.Contains("redemption temporarily unavailable"))
      {
          try
          {
              // 退回使用未變更的 body，仍附帶該 token
              response = await client.Beta.Messages.Create(exactBody);
          }
          catch (AnthropicBadRequestException retryError)
              when (!retryError.Message.Contains("redemption temporarily unavailable"))
          {
              // token 本身遭到拒絕：放棄它並在不附帶 token 的情況下重試。
              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)
  }
  // 非暫時性的 400 表示此嘗試形式或權杖已被拒絕，
  // 應執行階梯的下一階。「redemption temporarily
  // unavailable」屬暫時性：將其呈現出來，並在權杖的
  // 五分鐘時限內使用該權杖重試。
  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
  		// 除非宣告為 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) {
  			// 退回使用未變更的主體，仍附帶權杖
  			response, err = send(anthropic.ModelClaudeOpus4_8, exactBody)
  			if err != nil && canFallBack(err) {
  				// 權杖本身被拒絕：放棄該權杖並在不附帶它的情況下重試。
  				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);
          // 除非該宣告為假，否則優先採用延續形式
          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) {
              // 暫時性錯誤：在權杖的五分鐘有效期內使用該權杖重試
              if (badRequest.getMessage().contains("redemption temporarily unavailable")) {
                  throw badRequest;
              }
              try {
                  // 退回使用未變更的主體，仍附帶權杖
                  response = send(Model.CLAUDE_OPUS_4_8, request().fallbackCreditToken(creditToken));
              } catch (BadRequestException retryBadRequest) {
                  if (retryBadRequest.getMessage().contains("redemption temporarily unavailable")) {
                      throw retryBadRequest;
                  }
                  // 權杖本身遭拒：放棄該權杖並在不附帶權杖的情況下重試。
                  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;
      // 除非該宣告為假，否則優先採用延續形式
      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];
      }
      // 暫時性錯誤：在權杖的五分鐘有效期內使用該權杖重試
      $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 {
              // 退回使用未變更的主體，仍附帶權杖
              $response = $send('claude-opus-4-8', $messages, $token);
          } catch (BadRequestException $retryError) {
              if ($isTransientRedemption($retryError)) {
                  throw $retryError;
              }
              // 權杖本身遭拒：放棄該權杖並在不附帶權杖的情況下重試。
              $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)

    # 除非宣告為假，否則優先採用延續形式
    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
      # 暫時性錯誤：在五分鐘有效期內使用該 token 重試
      raise if error.message.include?("redemption temporarily unavailable")
      begin
        # 退回使用未變更的主體，仍附帶該 token
        response = send_message.call("claude-opus-4-8", exact_body)
      rescue Anthropic::Errors::BadRequestError => error
        # 暫時性錯誤：在五分鐘有效期內使用該 token 重試
        raise if error.message.include?("redemption temporarily unavailable")
        # token 本身遭拒：放棄該 token 並在不附帶它的情況下重試。
        response = send_message.call("claude-opus-4-8", request)
      end
    end
  end

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

## 適用範圍

備援抵免目前在 Claude API、Amazon Bedrock、Claude Platform on AWS、Google Cloud 和 Microsoft Foundry 上處於 beta 階段。[Message Batches](https://platform.claude.com/docs/zh-TW/build-with-claude/batch-processing) 中的拒絕不會產生抵免權杖，且兌換僅適用於直接的 Messages API 請求：在批次請求中傳入的權杖會被接受但會被忽略。Claude Haiku 5.5 的拒絕不附帶備援抵免，因此在其拒絕後進行的重試需支付寫入備援模型提示快取的全額費用。

重試模型必須是被拒絕模型所允許的備援目標之一。對於 Claude Fable 5.1、Claude Fable 5 和 Claude Opus 5.5，允許的目標為 Claude Opus 4.8（`claude-opus-4-8`）和 Claude Opus 5（`claude-opus-5`）。對於 Claude Opus 5，目標為 Claude Opus 4.8。對於 Claude Sonnet 5.5，目標為 Claude Sonnet 5（`claude-sonnet-5`）。

<Accordion title="以程式方式查詢允許的備援目標">
  在 Claude API 與 Claude Platform on AWS 上，當設定了 `server-side-fallback-2026-07-01` beta 標頭時，目標清單會以 `allowed_fallback_models` 的形式發布於 [Models API](https://platform.claude.com/docs/zh-TW/api/models/list) 中每個模型的項目上。僅使用 `fallback-credit-*` 標頭時，該清單尚不可見。它在 Amazon Bedrock、Google Cloud 或 Microsoft Foundry 上不會公開。
</Accordion>

## 確認抵免已套用

退款可在重試的 `usage` 中看到。與同一請求在沒有權杖時所回報的數值相比，`cache_creation_input_tokens` 較低，而 `cache_read_input_tokens` 則高出相同的數量。若變動為零，表示權杖已被接受，但沒有需要重新計價的項目，例如因為重試模型的快取已經是熱的。

## 當重試被拒絕時

大多數重試在第一次嘗試時即可兌換。若未能兌換，API 會回傳一個 400 錯誤，告訴您接下來該嘗試什麼。

<Steps>
  <Step title="接續被拒絕：重新傳送未變更的主體">
    如果附加 assistant 訊息的重試被以 400 錯誤拒絕，請重新傳送未變更的被拒絕請求主體，仍附上權杖。
  </Step>

  <Step title="權杖被拒絕：移除權杖">
    如果未變更的主體也被以 400 錯誤拒絕，且錯誤訊息中提及 `fallback_credit_token`，請在不附權杖的情況下重試。抵免會被放棄，但重試本身會成功送出。
  </Step>
</Steps>

<Note>
  如果被拒絕的請求執行了伺服器工具，不附權杖的重試會重新執行並重新計費這些工具。在這種情況下，請將 400 錯誤呈現給您的呼叫端，而非繼續進行不附權杖的重試。
</Note>

<Accordion title="如果錯誤顯示「redemption temporarily unavailable」">
  此拒絕是暫時性的，並非對您重試形式的判定。請在權杖的五分鐘有效期內，使用相同的權杖重試相同的請求。不要進入階梯的下一步。
</Accordion>

## 參考

以下各節涵蓋邊緣案例與完整的兌換規則。大多數整合不需要這些內容。

<Accordion title="必須與被拒絕請求相符的欄位">
  兌換會將重試與被拒絕的請求進行比對。每個會影響提示內容的欄位都必須完全相符。不影響提示內容的欄位可以在重試時變更。

  | 規則      | 欄位                                                                                                                                               |
  | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
  | 必須完全相符  | `system`、`messages`、`tools`、`tool_choice`、`thinking` 與 `cache_control`，以及當您使用時的 `output_config`、`mcp_servers`、`context_management` 與 `container` |
  | 可在重試時變更 | `model`、`max_tokens`、`stop_sequences`、`temperature`、`top_p`、`top_k`、`stream`、`metadata` 與 `service_tier`                                         |

  接續形式（`fallback_has_prefill_claim: true`）是 `messages` 相符規則的唯一例外：它會在 `messages` 的末尾恰好新增一則 assistant 訊息。

  重試時不要從先前的輪次中移除 `thinking` 或 `redacted_thinking` 區塊，即使不附權杖的一般重試通常會移除它們。主體必須與被拒絕的請求相符，而伺服器會自行處理這些區塊。
</Accordion>

<Accordion title="Beta 標頭也必須相符">
  在重試時傳送與被拒絕請求相同的 `anthropic-beta` 標頭。若某個 beta 標頭只出現在兩個請求中的其中一個，即使主體完全相同，也可能導致比對失敗。所產生的 400 錯誤會帶有與主體差異相同的 `request body ... does not match` 訊息，因此標頭差異很容易被誤判為主體問題。特別是，不要根據請求所針對的模型來新增或移除 beta 標頭。

  為了重試的需要，有兩個標頭系列不受比對限制：

  * **`server-side-fallback-*`：** 重試必須移除 `fallbacks` 參數，而連同此標頭一併移除不會造成不相符。
  * **`fallback-credit-*`：** 在兩個請求上都保留此標頭。重試需要它才能兌換權杖。

  <Note>
    在預設包含 1M token 上下文視窗的模型上，例如 Claude Fable 5.1、Claude Fable 5、Claude Opus 5.5、Claude Opus 5、Claude Opus 4.8、Claude Sonnet 5.5 和 Claude Sonnet 5，`context-1m-2025-08-07` beta 標頭沒有作用。為了讓兩個請求保持一致，請在兩者上都省略該標頭，而不是只在其中一個上傳送。
  </Note>
</Accordion>

<Accordion title="當 fallback_has_prefill_claim 不存在時">
  只有在權杖也沒有值時，此欄位才會沒有值，因此當您持有權杖時，此欄位會有值；但 Amazon Bedrock、Google Cloud 和 Microsoft Foundry 除外，在這些平台逐步推出對此欄位的支援期間，它仍可能不存在。在這種情況下，請將重試形式視為未知，而不是視為 `false` (python: `False`)。請先嘗試附加 assistant 訊息的形式，並依賴[當重試被拒絕時](https://platform.claude.com/docs/zh-TW/build-with-claude/fallback-credit#when-a-retry-is-rejected)中的拒絕處理，它會退回到未修改的主體。
</Accordion>

<Accordion title="回傳被拒絕回應的 content">
  當拒絕的權杖支援接續形式時，回應的 `content` 僅包含模型自身的輸出，而拒絕說明則透過 `stop_details.explanation` 傳遞。因此您可以將 `content` 原樣回傳到附加的 assistant 訊息中。

  傳送前可能仍需要兩項調整：

  * 如果您傳送的最後一個區塊是 `text` 區塊，請移除其結尾的空白字元。
  * 省略任何沒有對應 `tool_result` 的用戶端 `tool_use` 區塊。

  如果回傳的內容包含來自先前[伺服器端備援](https://platform.claude.com/docs/zh-TW/build-with-claude/refusals-and-fallback#server-side-fallback)的 `fallback` 區塊，請將該區塊保留在其原本出現的確切位置。它在任何請求中都會被接受，無需 beta 標頭。API 會使用其位置來驗證其周圍的 thinking 區塊，因此若該區塊被省略或移動，回傳該邊界兩側 thinking 區塊的請求將被拒絕。
</Accordion>

<Accordion title="權杖範圍與有效期">
  權杖只能由收到拒絕的組織與工作區兌換，包括在 Microsoft Foundry 上。在沒有工作區的 Amazon Bedrock 與 Google Cloud 上，權杖則改為綁定至該平台的呼叫者身分。

  權杖在拒絕後五分鐘到期。之後，請在不附權杖的情況下傳送重試。權杖也是無狀態的：伺服器不會儲存任何與其相關的資訊，也沒有可用於檢視或撤銷它的端點。
</Accordion>

<Accordion title="當權杖無法以任一形式兌換時">
  當拒絕發生在請求中伺服器工具已執行之後，權杖只能透過接續部分回應來兌換。正是這項限制防止了已完成的工具呼叫再次執行與計費。

  因此，當以下兩項同時成立時，有一種組合可能導致權杖無法以任一形式兌換：

  * 請求使用了 `output_config.format` 或強制工具使用的 `tool_choice`。任一者都會排除附加 assistant 訊息的形式。
  * 拒絕發生在伺服器工具已執行之後。這會排除未變更的主體。

  如果未變更主體的重試被以 400 錯誤拒絕，且錯誤表示權杖必須透過接續部分回應來兌換，請捨棄該權杖。不附權杖的重試會成功送出，但它會重新執行並重新計費已完成的伺服器工具。請將費用或錯誤呈現給您的呼叫端，而非靜默重試。
</Accordion>

## 後續步驟

<CardGroup>
  <Card title="拒絕與備援" icon="shield" href="https://platform.claude.com/docs/zh-TW/build-with-claude/refusals-and-fallback">
    偵測拒絕，並在伺服器端備援、SDK 中介軟體與手動重試之間做出選擇。
  </Card>

  <Card title="提示快取" icon="bolt" href="https://platform.claude.com/docs/zh-TW/build-with-claude/prompt-caching">
    快取讀取與快取寫入的計費方式。
  </Card>

  <Card title="停止原因與備援" icon="code" href="https://platform.claude.com/docs/zh-TW/build-with-claude/handling-stop-reasons">
    每個 `stop_reason` 值及其處理方式。
  </Card>

  <Card title="SDK 中介軟體" icon="settings" href="https://platform.claude.com/docs/zh-TW/cli-sdks-libraries/middleware">
    自動套用備援抵免的 SDK 輔助工具。
  </Card>
</CardGroup>
