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

# Store Blob

> Upload data to Walrus network via Publisher

<Note>
  The Walrus Publisher handles preparing data for storage, paying the storage fees, and managing the transaction with the Walrus network.
</Note>

## Store Blob

Adds a blob to the Walrus network. The blob data is sent in the request body. The Publisher will handle preparing the data for storage, paying the storage fees, and managing the transaction with the Walrus network.

### Base URL

```bash theme={null}
https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/
```

Where `${endpoint_key}` is your specific endpoint key.

### Query Parameters

<ParamField query="epochs" optional>
  Number of storage epochs to store the blob (default: 1)
</ParamField>

<ParamField query="send_object_to" optional>
  Sui address to send the blob object to
</ParamField>

<ParamField query="deletable" optional>
  Whether the blob should be stored as deletable (default: false)
</ParamField>

### Request Examples

<RequestExample>
  ```bash Bash theme={null}
  # Store a string for 1 storage epoch
  curl -X PUT "https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs" \
    -d "some string"

  # Store a file for 5 storage epochs
  curl -X PUT "https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs?epochs=5" \
    --upload-file "some/file"

  # Store a file and send the blob object to a specific address
  curl -X PUT "https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs?send_object_to=${ADDRESS}" \
    --upload-file "some/file"

  # Store a file as a deletable blob
  curl -X PUT "https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs?deletable=true" \
    --upload-file "some/file"
  ```

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

  # Set your endpoint key
  endpoint_key = "your_endpoint_key"
  publisher_url = f"https://walrus-mainnet-publisher.nami.cloud/{endpoint_key}/v1/blobs"

  # Store a string
  response = requests.put(publisher_url, data="some string")
  print(response.json())

  # Store a file for 5 epochs
  with open("some/file", "rb") as file:
      response = requests.put(f"{publisher_url}?epochs=5", data=file)
      print(response.json())
  ```

  ```javascript Node.js theme={null}
  // Store a string
  fetch(`https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs`, {
    method: 'PUT',
    body: 'some string'
  })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

  // Store a file for 5 epochs
  const fs = require('fs');
  const fileData = fs.readFileSync('some/file');
  fetch(`https://walrus-mainnet-publisher.nami.cloud/${endpoint_key}/v1/blobs?epochs=5`, {
    method: 'PUT',
    body: fileData
  })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));
  ```

  ```go Golang theme={null}
  package main

  import (
  	"fmt"
  	"log"
  	"os"

  	"github.com/namihq/walrus-go"
  )

  func main() {
  	// Create a new client with default endpoints
  	client := walrus.NewClient()

  	// Or specify custom endpoints
  	// client := walrus.NewClient(
  	//     walrus.WithPublisherURLs([]string{"https://walrus-mainnet-publisher.nami.cloud/your-endpoint-key"}),
  	// )

  	// Example 1: Store a byte array
  	data := []byte("Hello, Walrus!")
  	resp, err := client.Store(data, &walrus.StoreOptions{
  		Epochs: 5, // Store for 5 epochs
  	})
  	if err != nil {
  		log.Fatalf("Error storing data: %v", err)
  	}
  	
  	// The blobId can be used to retrieve the data later
  	if resp.NewlyCreated != nil {
  		fmt.Printf("Stored new blob with ID: %s\n", resp.NewlyCreated.BlobObject.BlobId)
  		fmt.Printf("Storage cost: %d\n", resp.NewlyCreated.Cost)
  	} else if resp.AlreadyCertified != nil {
  		fmt.Printf("Blob already exists with ID: %s\n", resp.AlreadyCertified.BlobId)
  		fmt.Printf("Valid until epoch: %d\n", resp.AlreadyCertified.EndEpoch)
  	}

  	// Example 2: Store a file
  	filePath := "example.txt"
  	fileResp, err := client.StoreFile(filePath, &walrus.StoreOptions{
  		Epochs: 10, // Store for 10 epochs
  	})
  	if err != nil {
  		log.Fatalf("Error storing file: %v", err)
  	}
  	
  	if fileResp.NewlyCreated != nil {
  		fmt.Printf("Stored file with blob ID: %s\n", fileResp.NewlyCreated.BlobObject.BlobId)
  	}
  	
  	// Example 3: Store from URL
  	urlResp, err := client.StoreFromURL("https://example.com/sample.jpg", &walrus.StoreOptions{
  		Epochs: 3,
  	})
  	if err != nil {
  		log.Fatalf("Error storing from URL: %v", err)
  	}
  	
  	if urlResp.NewlyCreated != nil {
  		fmt.Printf("Stored URL content with blob ID: %s\n", urlResp.NewlyCreated.BlobObject.BlobId)
  	}
  	
  	// Example 4: Store with encryption
  	encryptedResp, err := client.Store([]byte("Secret data"), &walrus.StoreOptions{
  		Epochs: 5,
  		Encryption: &walrus.EncryptionOptions{
  			Key: []byte("a-32-byte-key-for-aes-256-encryption"), // 32 bytes for AES-256
  		},
  	})
  	if err != nil {
  		log.Fatalf("Error storing encrypted data: %v", err)
  	}
  	
  	if encryptedResp.NewlyCreated != nil {
  		fmt.Printf("Stored encrypted data with blob ID: %s\n", encryptedResp.NewlyCreated.BlobObject.BlobId)
  	}
  }
  ```
</RequestExample>

### Response - Newly Created Blob

When a blob is stored for the first time, a `newlyCreated` field contains information about the new blob:

```json theme={null}
{
  "newlyCreated": {
    "blobObject": {
      "id": "0xe91eee8c5b6f35b9a250cfc29e30f0d9e5463a21fd8d1ddb0fc22d44db4eac50",
      "registeredEpoch": 34,
      "blobId": "M4hsZGQ1oCktdzegB6HnI6Mi28S2nqOPHxK-W7_4BUk",
      "size": 17,
      "encodingType": "RS2",
      "certifiedEpoch": 34,
      "storage": {
        "id": "0x4748cd83217b5ce7aa77e7f1ad6fc5f7f694e26a157381b9391ac65c47815faf",
        "startEpoch": 34,
        "endEpoch": 35,
        "storageSize": 66034000
      },
      "deletable": false
    },
    "resourceOperation": {
      "registerFromScratch": {
        "encodedLength": 66034000,
        "epochsAhead": 1
      }
    },
    "cost": 132300
  }
}
```

### Response - Already Certified Blob

When the publisher finds a certified blob with the same blob ID and a sufficient validity period, it returns an `alreadyCertified` JSON structure:

```json theme={null}
{
  "alreadyCertified": {
    "blobId": "M4hsZGQ1oCktdzegB6HnI6Mi28S2nqOPHxK-W7_4BUk",
    "event": {
      "txDigest": "4XQHFa9S324wTzYHF3vsBSwpUZuLpmwTHYMFv9nsttSs",
      "eventSeq": "0"
    },
    "endEpoch": 35
  }
}
```

The field `event` returns the Sui event ID that can be used to find the transaction that created the Sui Blob object on the Sui explorer or using a Sui SDK.
