Volumes
Durable block storage a session can attach to, independent of any single session's lifetime.
What a volume is
A volume is a block of persistent disk storage you create once and attach to sessions as needed. A session's own disk goes away with the session; a volume doesn't — attach it to a later session and your files are still there.
Create one, then attach it by id on session create:
curl -X POST https://api.inis.run/v1/volumes \
-H "Authorization: Bearer $INIS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"size_gb": 5}'{
"id": "vol_7f3ac21b9e4d",
"size_gb": 5,
"created_at": "2026-08-07T10:00:00Z",
"attached": false
}A brand-new volume has no last_saved_at — it's omitted entirely until the volume has actually been through a session that ended (see "Durability" below).
curl -X POST https://api.inis.run/v1/sessions \
-H "Authorization: Bearer $INIS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"volume_id": "vol_7f3ac21b9e4d"}'volume_id also works on one-shot exec.
A volume must exist before you can attach it — volume_id naming an id you don't own, or one that doesn't exist, is a 404. Earlier versions of this API created a volume implicitly the first time an arbitrary name was attached; that no longer happens, so a typo in volume_id fails loudly instead of quietly provisioning a second, empty volume.
Only one session can hold a volume attached at a time — a live or paused session that already has it makes it unavailable to attach elsewhere until that session ends.
Managing volumes
| Endpoint | What it does |
|---|---|
POST /v1/volumes | Create one. {"size_gb": 5} — size_gb is optional, defaults to 1, capped at 10 |
GET /v1/volumes | List every volume you own |
GET /v1/volumes/{id} | Size, creation time, last_saved_at, and whether a live or paused session currently has it attached |
PATCH /v1/volumes/{id} | Grow it. {"size_gb": 8} — grow-only, refused while attached |
DELETE /v1/volumes/{id} | Permanently erase it |
curl https://api.inis.run/v1/volumes \
-H "Authorization: Bearer $INIS_TOKEN"{
"volumes": [
{ "id": "vol_7f3ac21b9e4d", "size_gb": 5, "created_at": "2026-08-07T10:00:00Z", "attached": true, "session_id": "s_Lp93Vt0c", "last_saved_at": "2026-08-06T18:42:00Z" }
]
}The console's Volumes page covers the same create/list/delete surface, and the session create form there offers your volumes as a picker instead of a typed-in id.
Deleting
curl -X DELETE https://api.inis.run/v1/volumes/vol_7f3ac21b9e4d \
-H "Authorization: Bearer $INIS_TOKEN"Refused with 409 while the volume is attached to a live or paused session — end that session first. This is permanent: it erases both the local copy and the durable off-node copy described below, with no recovery.
Sizing and resizing
size_gb defaults to 1 GiB at creation and is capped at 10 GiB per volume. Grow it later:
curl -X PATCH https://api.inis.run/v1/volumes/vol_7f3ac21b9e4d \
-H "Authorization: Bearer $INIS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"size_gb": 8}'A few things worth knowing before you rely on it:
- Grow-only.
size_gbmust be strictly greater than the volume's current size — a request at or below the current size is rejected (400), not treated as a shrink or a silent no-op. There's no way to shrink a volume through the API; shrinking a filesystem that has data in it isn't safe, so this refuses rather than attempting it. If you need less space, create a new, smaller volume and copy the data across. - Detach it first. A resize is refused with
409while the volume is attached to a live or paused session, or while an attach/detach is briefly in progress. Growing a disk image and its filesystem underneath a running VM isn't done live — end or pause-then-resume-elsewhere the session, resize, then reattach. - Takes effect on the next attach, not instantly. A successful
PATCHupdates the volume's registered size right away, but the physical disk image only grows the next time something actually attaches the volume — which, since resize is refused while attached, is the very next attach after the resize call returns. You won't see or need to wait for this separately; it just means the size change and the attach that uses it happen together. - Same total-provisioned-GB account ceiling as create applies to growth too — a resize that would push your account over its quota is rejected with
409, naming the limit and your current usage, exactly like an over-quota create.
Durability — what's actually guaranteed
A volume's data is durable as of the last time its session ended, not continuously:
- A volume's contents are pushed to EU object storage when the session using it is destroyed (not on pause — a paused session still holds the volume attached). The saved copy is encrypted with a key scoped to your account.
- Attaching a volume on a node that doesn't already hold a local copy restores it from that durable copy first.
- Writes made during a session are only durable once the session ends. While a session is running, its writes exist only on the machine running it. If that machine is lost mid-session, work since the volume's last push is lost with it.
- Deleting a volume erases both the local image and the durable copy — the durable copy is crypto-shredded (its encryption key is destroyed), not just marked deleted.
If you're writing something you cannot afford to lose, treat a volume like a working disk, not a backup: end the session (or checkpoint/copy the result out to your own storage) at the point you need the durability guarantee to apply.
last_saved_at
Every volume response carries last_saved_at: the timestamp of the most recent successful push described above. It answers "is my data actually safe, and as of when" directly — check it before trusting a volume with something you can't afford to lose.
- It's absent (not present in the response at all — never a zeroed or fabricated timestamp) on a volume that has never gone through a session that ended. A missing
last_saved_atmeans there is no durable copy yet; everything on that volume today exists only on whichever node it's currently attached to. - It updates on session destroy, same as the rest of this section — pausing a session does not move it forward. If a session has been running (or sitting paused) for a while,
last_saved_atstill reflects the last time it was actually destroyed and re-pushed, not "just now." - It is not a guarantee that nothing has changed since — a live or paused session can have written more to the volume than
last_saved_atreflects. It only tells you when the durable copy was last confirmed complete.
Best practices
Patterns that get good default behavior out of sessions — persistence, starting fast, scoped credentials, and locked-down egress.
Production best practices
Session lifecycle knobs, why you don't need your own warm pool, bulk file transfer, idempotent creates, reconnecting after resume, pagination, and retries.