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

# Writing

Writes are Solana transactions signed by your keypair or connected wallet. There is no upload service and no credentials: the wallet that signs owns the tape it writes to ([how the pieces fit](/protocol/architecture/overview)). This page covers the write engine. Reserving the tape it writes into is in the [quickstart](/sdks/quickstart).

## One call, dispatched by size

You call write; the engine picks the path. Small payloads become inline tracks that ride the transaction itself. Mid-size payloads become erasure-coded tracks. Large payloads stream in segments with a manifest ([tracks](/protocol/architecture/tracks) covers the model, [tape replay](/protocol/architecture/tape-replay) covers why small writes are cheap).

The size boundaries are client configuration with sensible defaults. They are not protocol limits.

<Frame caption="One write call, three paths, all ending at a certified track.">
  <img src="https://mintcdn.com/tapedrive/IVlwjOpRsvR7xk5g/images/write-dispatch.svg?fit=max&auto=format&n=IVlwjOpRsvR7xk5g&q=85&s=f42144434cd8aa544fba152512a0b8e2" alt="Payload size flowing into inline, coded, or stream paths, each ending at a certified track." width="897" height="297" data-path="images/write-dispatch.svg" />
</Frame>

<CodeGroup>
  ```rust Rust theme={null}
  let small = client.write_raw(&tape, &note_bytes).await?;         // inline
  let medium = client.write_bytes(&tape, &photo_bytes).await?;     // erasure-coded
  let large = client.write_stream(&tape, size, file).await?;       // any AsyncRead source + size
  ```
</CodeGroup>

## The write options

Names and content types are method arguments. The `write_named` variants and `put_object` take them directly ([objects](/sdks/objects)). A [delegate](/protocol/architecture/tapes#delegation) can sign on the owner's behalf without holding the owner's wallet. `WriteOptions` holds the tuning knobs, covered under [operational configuration](#operational-configuration).

## The receipt

`write_bytes` and `write_stream` return a `StreamReceipt`. Its fields:

* `tape`: the tape's address.
* `manifest`: the manifest track's address. This is what you read back.
* `manifest_track_number`: the manifest's track number on the tape.
* `manifest_value_hash`: the manifest's value hash, used as the content ETag.

Writing again under the same name creates a new track, and listings resolve to the latest. Nothing is updated in place ([objects](/sdks/objects) covers replace semantics).

## Certify: finishing the write

An erasure-coded write is finished when certified. Certification is the network's proof that your data is held: a quorum of the storage nodes that received your slices signs, and the aggregate signature lands on-chain ([what certification promises](/protocol/architecture/tracks)).

There is nothing to call. Every one-call write path runs peer discovery, signature collection, aggregation, and the certification transaction internally before it returns.

<CodeGroup>
  ```rust Rust theme={null}
  // Nothing to call: write_bytes / write_track certified before returning.
  // Staged pipelines re-run the finish with client.certify(&tape, &written).
  ```
</CodeGroup>

Two failure modes come up. **Insufficient signatures**: fewer than 14 of the group's 20 nodes answered in time. **Node visibility timeout**: the nodes haven't observed the registration yet. In both cases, retry certify. Signature collection resumes; the write is not lost. If you're unsure where things stand, check the track's state on chain before assuming failure.

## Error recovery mid-write

What an interruption leaves behind, stage by stage:

* A failed setup transaction leaves nothing.
* A registered-but-undistributed track holds tape capacity but is uncertified. Retry distribution, or delete it to free the capacity.
* A distributed-but-uncertified track needs only certify retried.

When in doubt, re-run the one-call write with the same inputs. It creates a new track, and you can delete the orphan if capacity matters ([tracks](/protocol/architecture/tracks) has the state machine).

## Operational configuration

The engine exposes three kinds of tuning: distribution concurrency, retry and pacing, and progress callbacks. All are client-side defaults, none are protocol limits. Touch them for large batches, constrained networks, or UI progress feedback.

<CodeGroup>
  ```rust Rust theme={null}
  let client = Tapedrive::new(rpc, payer)
      .with_write_options(WriteOptions { slice_concurrency: 8, store_depth: 4 });
  let receipt = client.write_bytes(&tape, &data).await?;
  ```
</CodeGroup>

## The staged pipeline

For pipeline builders who need control between stages, or anyone who wants to see what the one-call write does. The same upload, stage by stage:

1. **Encode.** Slice the file and compute its commitments locally. Nothing has touched the network yet ([slicing](/protocol/architecture/slicing)).
2. **Register.** Submit the registration transaction: it commits the track's Merkle root to the tape, deducts capacity, and assigns the spool group, the set of nodes that will hold its slices ([tracks](/protocol/architecture/tracks)).
3. **Distribute.** Push each slice with its proof to the group's nodes. Each node verifies against the on-chain commitment before accepting, and returns its signature.
4. **Certify.** Aggregate the collected signatures and submit. The write is finished when this lands.

<CodeGroup>
  ```rust Rust theme={null}
  // The explicit coded path runs all four stages, certification included:
  let track = client.write_track(&tape, &data).await?;
  // Pipeline builders re-run the finish alone with client.certify(&tape, &written).
  ```
</CodeGroup>

The one-call write performs exactly these stages, with retries and pacing built in.

## Managing tapes

The lifecycle operations, each a line here and a full entry on [docs.rs](https://docs.rs/tape-sdk). Semantics live on the [tapes page](/protocol/architecture/tapes).

* **Price before reserving**: cost estimation for a capacity and duration.
* **Extend**: add capacity or epochs. Permissionless, so anyone can pay to extend any tape.
* **Delegate / revoke**: grant or remove a write delegate.
* **Delete tracks**: an on-chain operation that frees capacity.

<CodeGroup>
  ```rust Rust theme={null}
  let cost = client.estimate_cost(capacity, epochs).await?;
  client.extend_capacity(&tape, more_bytes).await?;
  client.extend_expiry(&tape, more_epochs).await?;
  client.set_tape_delegate(&tape, delegate_address).await?;
  client.delete(&tape, track_address).await?;
  ```
</CodeGroup>
