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

# Reserved TPM

> Reserve guaranteed serverless inference capacity in advance, for no extra charge

> [!NOTE]
>
> Reserved TPM is in Beta and available to select pilot customers. To join the
> waitlist, send us a note from the support form in your [Sail
> dashboard](https://app.sailresearch.com) (recommended), or [contact
> support](https://www.sailresearch.com/support).

With Reserved TPM, you can reserve dedicated serverless inference capacity
ahead of time in the form of uncached input and output tokens per minute (TPM),
on your selected model and service tier.

You can think of Reserved TPM as **prepaying for tokens** (at your normal
per-token rates) **in exchange for guaranteed TPM**. Reserved TPM also **removes the
[queueing time](https://docs.sailresearch.com/service-tiers.md#service-tier-comparison) associated with
Balanced and Flex altogether.**

Reserved TPM is fully self-serve and available on Pro and Enterprise plans.

## How it works

* You can book Reserved TPM for a start time at least one hour in advance.
  You will specify:
  * The **model and service tier**
    * *Optional*: The **LoRA name or ID**, if reserving throughput for your LoRA
      fine-tuned model (note - you must [upload your LoRA to Sail](https://docs.sailresearch.com/loras.md)
      first).
  * The **duration of the reservation** in hours, from 1 hour to 3 days long
  * The **reservation start time**, from 1 hour to 7 days in advance
  * The **uncached input TPM** amount to reserve
  * The **output TPM** amount to reserve
* There is no surcharge for Reserved TPM. The cost of a reservation is simply
  the cost of pre-paying for the reserved uncached input and output token
  volume ahead of time: your normal per mTok rates (see [Pricing](https://docs.sailresearch.com/pricing.md)),
  applied to the TPM and duration you reserve.
* **Eligible inference usage during your reservation is guaranteed to be able
  to meet or exceed the throughput limits you reserved.**
* The cost of eligible inference usage during the reservation period first
  draws down from the prepayment from when you booked the Reserved TPM, then is
  billed as regular usage once the total prepayment is depleted.

> [!TIP]
>
> If your Sail account uses prepaid credits (Pro plan) instead of monthly
> invoicing (Enterprise plan), be sure to have enough credits in your balance to
> cover eligible usage beyond the reservation prepayment. This is important
> because the prepayment doesn't include the cost of any cached input token
> volume. (See: [What if my org's credit balance runs out during a
> reservation?](#what-if-my-orgs-credit-balance-runs-out-during-a-reservation))

## Book and use Reserved TPM

Send `POST /v1/reserved-tpm` with an `Idempotency-Key` header:

> [tab] Base model
>
> ```python Python theme={null}
> from datetime import datetime, timezone
>
> import sail
>
> reservation = sail.ReservedTpm.create(
>     model="deepseek/deepseek-v4-pro-0813",
>     service_tier="flex",
>     starts_at=datetime(2026, 11, 20, 16, tzinfo=timezone.utc),
>     duration_hours=4,
>     uncached_input_tpm=1_000_000,
>     output_tpm=200_000,
> )
>
> print(reservation.id, reservation.status)
> ```
>
> ```typescript TypeScript theme={null}
> import { ReservedTpm } from "@sailresearch/sdk";
>
> const reservation = await ReservedTpm.create({
>   model: "deepseek/deepseek-v4-pro-0813",
>   serviceTier: "flex",
>   startsAt: new Date("2026-11-20T16:00:00Z"),
>   durationHours: 4,
>   uncachedInputTpm: 1_000_000,
>   outputTpm: 200_000,
> });
>
> console.log(reservation.id, reservation.status);
> ```
>
> ```bash cURL theme={null}
> curl https://api.sailresearch.com/v1/reserved-tpm \
>   -H "Authorization: Bearer $SAIL_API_KEY" \
>   -H "Content-Type: application/json" \
>   -H "Idempotency-Key: 9a8b1fc3-b9da-4b14-bb9b-98978c814b2d" \
>   -d '{
>     "model": "deepseek/deepseek-v4-pro-0813",
>     "service_tier": "flex",
>     "starts_at": "2026-11-20T16:00:00Z",
>     "duration_hours": 4,
>     "uncached_input_tpm": 1000000,
>     "output_tpm": 200000
>   }'
> ```

> [tab] LoRA fine-tune
>
> ```python Python theme={null}
> from datetime import datetime, timezone
>
> import sail
>
> reservation = sail.ReservedTpm.create(
>     model="zai-org/GLM-5.3",
>     service_tier="flex",
>     lora="funnier-v1",
>     starts_at=datetime(2026, 11, 20, 16, tzinfo=timezone.utc),
>     duration_hours=4,
>     uncached_input_tpm=1_000_000,
>     output_tpm=200_000,
> )
>
> print(reservation.id, reservation.status)
> ```
>
> ```typescript TypeScript theme={null}
> import { ReservedTpm } from "@sailresearch/sdk";
>
> const reservation = await ReservedTpm.create({
>   model: "zai-org/GLM-5.3",
>   serviceTier: "flex",
>   lora: "funnier-v1",
>   startsAt: new Date("2026-11-20T16:00:00Z"),
>   durationHours: 4,
>   uncachedInputTpm: 1_000_000,
>   outputTpm: 200_000,
> });
>
> console.log(reservation.id, reservation.status);
> ```
>
> ```bash cURL theme={null}
> curl https://api.sailresearch.com/v1/reserved-tpm \
>   -H "Authorization: Bearer $SAIL_API_KEY" \
>   -H "Content-Type: application/json" \
>   -H "Idempotency-Key: 4f2c8e1a-7b3d-4e9f-a6c5-2d8b1e0f9a73" \
>   -d '{
>     "model": "zai-org/GLM-5.3",
>     "service_tier": "flex",
>     "lora": "funnier-v1",
>     "starts_at": "2026-11-20T16:00:00Z",
>     "duration_hours": 4,
>     "uncached_input_tpm": 1000000,
>     "output_tpm": 200000
>   }'
> ```

| Field | Description |
| - | - |
| `model` | The model to reserve. |
| `service_tier` | `asap`, `balanced`, or `flex`. |
| `lora` | Optional. The name or ID of a [LoRA](https://docs.sailresearch.com/loras.md) on the model. The reservation then covers requests that use that LoRA. |
| `starts_at` | When the reservation starts, as an RFC 3339 time. |
| `duration_hours` | Whole hours, from 1 to 72. |
| `uncached_input_tpm` | Uncached input tokens per minute. |
| `output_tpm` | Output tokens per minute. |
| `routing.allowed_countries` | Optional. Set `["US"]` for a [US-only](https://docs.sailresearch.com/us-only-inference.md) reservation. |

Retrying with the same `Idempotency-Key` will return the same reservation.
Reusing a key with different fields will return HTTP `409`.

### Errors

| Status | Code | Meaning |
| - | - | - |
| `400` | `reservation_below_minimum` | The reservation is below the size required to use Reserved TPM for the model and service tier requested. |
| `400` | `model_not_available` | The model is not yet available via Reserved TPM. |
| `400` | `service_tier_not_available` | The model at the selected service tier is not yet available via Reserved TPM. |
| `402` | `credits_exhausted` | Your Sail credit balance isn't above the price. Add credits and book again. This is only applicable to non-enterprise organizations. |
| `409` | `capacity_unavailable` | The window you've requested is fully booked. `earliest_start` is the earliest start available for the reservation, or `null`. |

### Success

If the Reserved TPM you've requested is available, the reservation will be
booked immediately and the [cost](#how-it-works) will be deducted from your
balance. The response will contain the reservation.

### Reservation details

A reservation looks like:

```json theme={null}
{
  "id": "rtpm_019a9b2c-4f1e-7a3d-9c2b-5e8f1a0d6b47",
  "object": "reserved_tpm",
  "model": "deepseek/deepseek-v4-pro-0813",
  "service_tier": "flex",
  "lora": null,
  "starts_at": "2026-11-20T16:00:00Z",
  "ends_at": "2026-11-20T20:00:00Z",
  "duration_hours": 4,
  "uncached_input_tpm": 1000000,
  "output_tpm": 200000,
  "routing": null,
  "price": { "amount_cents": 17712, "currency": "USD" },
  "usage": { "consumed_cents": 0, "remaining_cents": 17712, "as_of": null },
  "free_cancel_until": "2026-11-13T18:12:11Z",
  "refund": null,
  "status": "booked",
  "created_at": "2026-11-13T18:02:11Z",
  "updated_at": "2026-11-13T18:02:11Z",
  "cancelled_at": null
}
```

| `status` | Meaning |
| - | - |
| `booked` | The reservation is confirmed. |
| `pending_charge` | Payment is still processing. Get the reservation to check again. |
| `charge_failed` | Payment failed. Nothing was charged and the capacity was released. |
| `cancelled` | You cancelled the reservation. |

`usage` shows how much of the reservation's prepayment balance is used
(`consumed_cents`) and left (`remaining_cents`), as of `as_of`. Note that
updates to `usage` may continue for up to several hours past the end, because
requests admitted near the end of the reservation can still use the value when
they finish.

### Use a reservation

Your inference requests need no changes. The requests you send during your
Reserved TPM window with the corresponding model and service tier will be
routed to your reserved capacity automatically.

Using Reserved TPM has the added benefit of removing the [request queueing
latency](https://docs.sailresearch.com/service-tiers.md#service-tier-comparison) that would otherwise be
incurred on the Balanced and Flex [service tiers](https://docs.sailresearch.com/service-tiers.md).

* [Responses API](https://docs.sailresearch.com/api-reference/responses-api/create-a-response.md)
* [Chat Completions API](https://docs.sailresearch.com/api-reference/chat-completions-api/create-a-chat-completion.md)
* [Messages API](https://docs.sailresearch.com/api-reference/messages-api/create-an-anthropic-message.md)

> [!WARNING]
>
> Don't use the [Batch API](https://docs.sailresearch.com/api-reference/batches-api/create-a-batch.md) for
> Reserved TPM. Batch requests aren't eligible for Reserved TPM SLAs.

### List reservations

List returns your organization's reservations, newest first, with `has_more`.
`limit` is 1 to 100 (default 20). To get the next page, pass the last ID as
`after_id`.

```python Python theme={null}
import sail

reservations = sail.ReservedTpm.list(limit=20)
```

```typescript TypeScript theme={null}
import { ReservedTpm } from "@sailresearch/sdk";

const reservations = await ReservedTpm.list({ limit: 20 });
```

```bash cURL theme={null}
curl "https://api.sailresearch.com/v1/reserved-tpm?limit=20" \
  -H "Authorization: Bearer $SAIL_API_KEY"
```

### Get a reservation

```python Python theme={null}
import sail

reservation = sail.ReservedTpm.get("rtpm_019a9b2c-4f1e-7a3d-9c2b-5e8f1a0d6b47")
```

```typescript TypeScript theme={null}
import { ReservedTpm } from "@sailresearch/sdk";

const reservation = await ReservedTpm.get(
  "rtpm_019a9b2c-4f1e-7a3d-9c2b-5e8f1a0d6b47",
);
```

```bash cURL theme={null}
curl https://api.sailresearch.com/v1/reserved-tpm/$RESERVATION_ID \
  -H "Authorization: Bearer $SAIL_API_KEY"
```

### Cancel a reservation

You can cancel a `booked` reservation to release the capacity, any time until
it ends.

**Free cancel grace period:** you can cancel Reserved TPM **within 10 minutes
of booking** for a full refund of the price in Sail credits. Your organization
gets one free cancellation in a rolling 24-hour window.

Otherwise, **reserved TPM is non-refundable**.

```python Python theme={null}
import sail

reservation = sail.ReservedTpm.get("rtpm_019a9b2c-4f1e-7a3d-9c2b-5e8f1a0d6b47")
cancelled = reservation.cancel()

print(cancelled.status, cancelled.refund)
```

```typescript TypeScript theme={null}
import { ReservedTpm } from "@sailresearch/sdk";

const reservation = await ReservedTpm.get(
  "rtpm_019a9b2c-4f1e-7a3d-9c2b-5e8f1a0d6b47",
);
const cancelled = await reservation.cancel();

console.log(cancelled.status, cancelled.refund);
```

```bash cURL theme={null}
curl -X POST https://api.sailresearch.com/v1/reserved-tpm/$RESERVATION_ID/cancel \
  -H "Authorization: Bearer $SAIL_API_KEY"
```

`free_cancel_until` shows when a free cancel stops being available, or `null`
when the reservation is not refundable. The response's `refund` contains
`amount_cents` and a `status` of `pending` until the credit is added, then
`refunded`. If nothing is refunded, `refund` is `null`.

## FAQ

> [accordion] How far ahead can I book Reserved TPM?
>
> At least 1 hour in advance. and at most 7 days in advance.

> [accordion] How long can a reservation be?
>
> From 1 hour to 3 days (72 hours), in whole hours.

> [accordion] Can I change a reservation?
>
> No, reservations can't be changed after booking.  You must cancel and book
> another reservation instead.

> [accordion] Who can use Reserved TPM?
>
> Reserved TPM is currently in waitlisted Beta. Soon, this feature will be
> open to all users on Pro and Enterprise plans.

> [accordion] How do I get access?
>
> Reserved TPM is in Beta, by request. Send us a note from the support form in
> your [Sail dashboard](https://app.sailresearch.com), or [contact
> support](https://www.sailresearch.com/support).

> [accordion] How far in advance can I book?
>
> Up to 7 days. If you need to book further out, [contact
> support](https://www.sailresearch.com/support).

> [accordion] Can I reserve TPM for a LoRA fine-tune?
>
> Yes. Book the LoRA's base model on Flex, with `lora` set to the LoRA's name
> or ID. That reservation covers requests that use that [LoRA](https://docs.sailresearch.com/loras.md). A
> reservation without `lora` covers only requests that don't use a LoRA.

> [accordion] Can I see how much of a reservation I've used?
>
> Yes, you can fetch the reservation and see the remaining value in the  `usage` field.

> [accordion] Does a reservation cover other service tiers?
>
> No. It covers only the reservation's designated model and tier. Requests on
> other tiers run as normal traffic.

> [accordion] How does billing work?
>
> You pre-pay your normal per-token prices for the entire reservation's token
> uncached input and output amount when you book. If your org is on the Pro
> plan, which uses prepaid credits for billing, you must have enough credits
> to make this upfront payment.

> [accordion] What happens if I cancel?
>
> Sail releases the capacity. Cancelling within 10 minutes of booking also
> refunds the full price as Sail credits, if you haven't already done such a
> cancellation in the past 24 hours. Any other cancellation is not eligible
> for a refund.

> [accordion] What happens to value I don't use?
>
> Unused value after the reservation ends is not refunded.

> [accordion] What's the smallest reservation?
>
> Each model and service tier combination has a minimum reservation size, in
> dollars per hour.

> [accordion] Does the reservation's value carry across minutes?
>
> Yes, monetary value rolls over minute to minute.
>
> To illustrate, if your reservation's value is \$100, any inference request
> with the correct model and service tier during the reservation window will
> draw down from that \$100 until it's depleted, regardless of when it's sent.
>
> However, the TPM guarantees of your reservation remain constant, so bursts
> over the guaranteed amounts may not be serviceable if there is not
> sufficient capacity.

> [accordion] What happens to usage above the reserved value during the reservation period?
>
> Those requests run and are billed as normal traffic, without the Reserved
> TPM SLA.

> [accordion] What if my org's credit balance runs out during a reservation?
>
> Eligible usage under the Reserved TPM booking specifications will continue
> as normal, since it is already prepaid, so long as the reservation's total
> value is not depleted. Other requests will return `402` until you add
> credits.

> [accordion] How does a US-only reservation work?
>
> **A US-only reservation makes the requests it covers US-only.** They run in
> the US and are billed as US-only, matching the reservation's price, even
> without `routing.allowed_countries`. Still we recommend setting this on the
> individual requests as well in case usage exceeds your reservation.
