---
title: Кредит при резервном переключении
url: https://platform.claude.com/docs/ru/build-with-claude/fallback-credit
description: Избегайте двойной оплаты стоимости кэша подсказок при повторной отправке отклонённого запроса на другую модель.
---

Кэши подсказок привязаны к конкретной модели. Когда модель отклоняет запрос и вы повторяете его на другой модели, префикс разговора, уже закэшированный для первой модели, должен быть записан в кэш новой модели с нуля. Запись в кэш стоит дороже, чем чтение из кэша. «Fallback credit» (кредит при резервном переключении) устраняет эту дополнительную стоимость. Отказ содержит токен кредита, вы передаёте этот токен обратно при повторной попытке, и повторная попытка тарифицируется так, как если бы разговор с самого начала вёлся на новой модели.

Эта страница нужна вам только в том случае, если вы реализуете повторную попытку самостоятельно: через «сырой» HTTP или с собственной логикой повторов. [Резервное переключение на стороне сервера](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#server-side-fallback) и [промежуточное ПО SDK](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#client-side-fallback) применяют кредит при резервном переключении автоматически. Если вы используете любой из этих вариантов, пропустите эту страницу.

Страница [Отказы и резервное переключение](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback) описывает обнаружение отказов и выбор подхода к резервному переключению. Страница [Кэширование подсказок](https://platform.claude.com/docs/ru/build-with-claude/prompt-caching) объясняет, что такое «cache reads» (чтение из кэша) и «cache writes» (запись в кэш), если эти термины вам незнакомы.

## Базовый процесс

<Steps>
  <Step title="Подключитесь с помощью бета-заголовка">
    Отправьте запрос, который может быть отклонён, с заголовком `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`. Заголовок необходим повторному запросу для погашения токена.
  </Step>
</Steps>

Поле `fallback_has_prefill_claim` сообщает, может ли повторный запрос продолжить частичный вывод отказавшей модели вместо того, чтобы начинать заново:

| `fallback_has_prefill_claim` | Тело повторного запроса                                                                                                                                                                                                                                                                                          |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `true`                       | Тело отклонённого запроса без изменений плюс одно добавленное в конец сообщение ассистента, чьё поле `content` повторяет `content` отклонённого ответа. Резервная модель продолжает ответ с того места, где остановилась отказавшая модель, а завершённые вызовы серверных инструментов не выполняются повторно. |
| `false`                      | Тело отклонённого запроса без изменений.                                                                                                                                                                                                                                                                         |

## Пример

В следующем примере выполняется запрос, который может быть отклонён, и токен кредита погашается при повторной попытке на Claude Opus 4.8. Когда повторная попытка отклоняется, пример последовательно спускается по «лестнице отклонений»: последовательности всё более простых форм повторного запроса, описанной в разделе [Когда повторный запрос отклонён](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit#when-a-retry-is-rejected).

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    Этот рабочий процесс требует больше логики, чем одна команда оболочки. Используйте [Claude SDK](https://platform.claude.com/docs/ru/cli-sdks-libraries/overview) для его запуска.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    Этот рабочий процесс требует больше логики, чем одна команда оболочки. Используйте [Claude SDK](https://platform.claude.com/docs/ru/cli-sdks-libraries/overview) для его запуска.
  </CodeGroupItem>

  ```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
      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:
              # Откат к неизменённому телу, по-прежнему с токеном
              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
              # Сам токен был отклонён: отказаться от него и повторить без него.
              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
    };

    // Сначала самая полная форма, с упрощением при каждом отказе: форма
    // продолжения (если утверждение не ложно), неизменённое тело, всё ещё
    // несущее токен, и, наконец, отказ от токена.
    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» — временная ошибка: вместо этого повторите тем же способом
      // в пределах пятиминутного окна действия токена.
      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;
      // Предпочитать форму продолжения, если только утверждение не ложно
      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: повторить с токеном в пределах его пятиминутного окна.
      try
      {
          response = await client.Beta.Messages.Create(attempt);
      }
      catch (AnthropicBadRequestException e)
          when (!e.Message.Contains("redemption temporarily unavailable"))
      {
          try
          {
              // Откат к неизменённому телу, по-прежнему с токеном
              response = await client.Beta.Messages.Create(exactBody);
          }
          catch (AnthropicBadRequestException retryError)
              when (!retryError.Message.Contains("redemption temporarily unavailable"))
          {
              // Сам токен был отклонён: отказаться от него и повторить без него.
              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
  		// Предпочитайте форму продолжения, если только утверждение не ложно
  		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
      # Временная ошибка: повторите с токеном в пределах его пятиминутного окна
      raise if error.message.include?("redemption temporarily unavailable")
      begin
        # Откат к неизменённому телу запроса, по-прежнему с токеном
        response = send_message.call("claude-opus-4-8", exact_body)
      rescue Anthropic::Errors::BadRequestError => error
        # Временная ошибка: повторите с токеном в пределах его пятиминутного окна
        raise if error.message.include?("redemption temporarily unavailable")
        # Сам токен был отклонён: откажитесь от него и повторите без него.
        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. Отказы в [Message Batches](https://platform.claude.com/docs/ru/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 на AWS список целей публикуется как `allowed_fallback_models` в записи каждой модели в [Models API](https://platform.claude.com/docs/ru/api/beta/models/list), когда установлен бета-заголовок `server-side-fallback-2026-07-01`. Список пока не виден при использовании только заголовка `fallback-credit-*`. Он не предоставляется на Amazon Bedrock, Google Cloud и Microsoft Foundry.
</Accordion>

## Проверка применения кредита

Возврат виден в поле `usage` повторного запроса. По сравнению с тем, что тот же запрос показал бы без токена, значение `cache_creation_input_tokens` ниже, а `cache_read_input_tokens` выше на ту же величину. Нулевой сдвиг означает, что токен был принят, но переоценивать было нечего, например потому, что кэш резервной модели уже был «прогрет».

## Когда повторный запрос отклонён

Большинство повторных запросов погашают токен с первой попытки. Если этого не происходит, API возвращает ошибку 400, которая подсказывает, что попробовать дальше.

<Steps>
  <Step title="Продолжение отклонено: отправьте тело без изменений">
    Если повторный запрос с добавленным сообщением ассистента отклонён с ошибкой 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`.

  Не удаляйте блоки `thinking` или `redacted_thinking` из предыдущих ходов в повторном запросе, даже несмотря на то, что обычный повторный запрос без токена, как правило, их удаляет. Тело должно совпадать с отклонённым запросом, а сервер обрабатывает эти блоки самостоятельно.
</Accordion>

<Accordion title="Бета-заголовки тоже должны совпадать">
  Отправляйте в повторном запросе те же заголовки `anthropic-beta`, что и в отклонённом. Бета-заголовок, присутствующий в одном из двух запросов, но отсутствующий в другом, может привести к несовпадению, даже если тела идентичны. Результирующая ошибка 400 содержит то же сообщение `request body ... does not match`, что и при различии тел, поэтому различие в заголовках легко ошибочно принять за проблему с телом. В частности, не добавляйте и не убирайте бета-заголовки в зависимости от того, на какую модель направлен запрос.

  Два семейства заголовков освобождены от проверки совпадения ради повторного запроса:

  * **`server-side-fallback-*`:** повторный запрос должен убрать параметр `fallbacks`, и удаление этого заголовка вместе с ним не вызывает несовпадения.
  * **`fallback-credit-*`:** сохраняйте этот заголовок в обоих запросах. Он необходим повторному запросу для погашения токена.

  <Note>
    В моделях, которые по умолчанию включают контекстное окно в 1M токенов, таких как 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` не имеет эффекта. Чтобы два запроса оставались идентичными, опустите этот заголовок в обоих, а не отправляйте его в одном и не отправляйте в другом.
  </Note>
</Accordion>

<Accordion title="Когда fallback_has_prefill_claim отсутствует">
  У поля нет значения только тогда, когда его нет и у токена, поэтому пока у вас есть токен, у поля есть значение, за исключением Amazon Bedrock, Google Cloud и Microsoft Foundry, где оно всё ещё может отсутствовать, пока разворачивается поддержка этого поля. В таком случае считайте форму повторного запроса неизвестной, а не `false` (python: `False`). Сначала попробуйте форму с добавленным сообщением ассистента и положитесь на обработку отклонений, описанную в разделе [Когда повторный запрос отклонён](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit#when-a-retry-is-rejected), которая переходит к телу без изменений.
</Accordion>

<Accordion title="Повторение content отклонённого ответа">
  Когда токен отказа поддерживает форму продолжения, поле `content` ответа содержит только собственный вывод модели, а объяснение отказа передаётся в `stop_details.explanation`. Поэтому вы можете повторить `content` в добавленном сообщении ассистента как есть.

  Перед отправкой всё же могут потребоваться две корректировки:

  * Если последний отправляемый вами блок — это блок `text`, удалите его завершающие пробельные символы.
  * Опустите любой клиентский блок `tool_use`, у которого нет соответствующего `tool_result`.

  Если повторяемое содержимое включает блок `fallback` от более раннего [резервного переключения на стороне сервера](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#server-side-fallback), сохраните блок точно на том месте, где он находился. Он принимается в любом запросе без бета-заголовка. API использует его позицию для проверки блоков размышлений вокруг него, поэтому запрос, повторяющий блоки размышлений с обеих сторон этой границы, отклоняется, если блок опущен или перемещён.
</Accordion>

<Accordion title="Область действия и срок жизни токена">
  Токен погашается только из той организации и рабочего пространства, которые получили отказ, в том числе на Microsoft Foundry. На Amazon Bedrock и Google Cloud, где нет рабочих пространств, токен вместо этого привязан к идентификатору вызывающей стороны на платформе.

  Срок действия токена истекает через пять минут после отказа. После этого отправляйте повторный запрос без него. Токен также не имеет состояния: сервер ничего о нём не хранит, и не существует конечной точки для его проверки или отзыва.
</Accordion>

<Accordion title="Когда токен нельзя погасить ни одной из форм">
  Если отказ поступил после того, как серверные инструменты уже были выполнены в рамках запроса, токен погашается только путём продолжения частичного ответа. Именно это ограничение предотвращает повторный запуск и повторную тарификацию завершённых вызовов инструментов.

  Поэтому одна комбинация может сделать токен непогашаемым ни одной из форм, когда верны оба следующих условия:

  * Запрос использовал `output_config.format` или `tool_choice`, принудительно требующий использования инструментов. Любое из них исключает форму с добавленным сообщением ассистента.
  * Отказ поступил после выполнения серверных инструментов. Это исключает тело без изменений.

  Если повторный запрос с телом без изменений отклонён с ошибкой 400, сообщающей, что токен должен быть погашен путём продолжения частичного ответа, отбросьте токен. Повторный запрос без него проходит, но заново запускает и заново тарифицирует завершённые серверные инструменты. Сообщите о стоимости или об ошибке вызывающей стороне, а не повторяйте запрос молча.
</Accordion>

## Следующие шаги

<CardGroup>
  <Card title="Отказы и резервное переключение" icon="shield" href="https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback">
    Обнаруживайте отказы и выбирайте между резервным переключением на стороне сервера, промежуточным ПО SDK и ручной повторной попыткой.
  </Card>

  <Card title="Кэширование подсказок" icon="bolt" href="https://platform.claude.com/docs/ru/build-with-claude/prompt-caching">
    Как тарифицируются чтение из кэша и запись в кэш.
  </Card>

  <Card title="Причины остановки и резервное переключение" icon="code" href="https://platform.claude.com/docs/ru/build-with-claude/handling-stop-reasons">
    Все значения `stop_reason` и способы их обработки.
  </Card>

  <Card title="Промежуточное ПО SDK" icon="settings" href="https://platform.claude.com/docs/ru/cli-sdks-libraries/middleware">
    Вспомогательный инструмент SDK, который применяет кредит при резервном переключении автоматически.
  </Card>
</CardGroup>
