ByteSpray Documentation

Learn how to store and retrieve data with full control over geographic location.

New to ByteSpray? Start with the Quickstart guide to store your first data in under 5 minutes.

What is ByteSpray?

ByteSpray is a distributed storage API that gives you complete control over where your data physically resides. Unlike traditional cloud storage:

  • Data Sovereignty: Choose specific countries/regions for your data via namespaces
  • Decentralized: Data is fragmented and distributed across multiple nodes
  • Encrypted: Per-namespace RSA-2048 encryption before data is fragmented
  • Compliant: Built for GDPR, HIPAA, PIPEDA requirements

Quickstart

Choisissez votre SDK, installez-le et commencez a stocker des donnees en quelques minutes.

1. Creer un Namespace

Connectez-vous au tableau de bord ByteSpray et creez un namespace. Selectionnez les regions ou vos donnees seront stockees. Vous recevrez une cle API (sp_xxx) et un secret API.

2. Telecharger et installer le SDK

Langage Version Telecharger
Python 3.8+ 1.0.0 spray-sdk-python-1.0.0.tar.gz
TypeScript / Node.js 18+ 1.0.0 spray-sdk-typescript-1.0.0.tar.gz
Go 1.21+ 1.0.0 spray-sdk-go-1.0.0.tar.gz
PHP 8.1+ 1.0.0 spray-sdk-php-1.0.0.tar.gz

Python

Terminal
wget https://bytespray.com/sdks/spray-sdk-python-1.0.0.tar.gz
tar -xzf spray-sdk-python-1.0.0.tar.gz
cd spray-sdk-python
pip install .
Python — Store, Retrieve, Update, Delete
from spray_sdk import SprayClient

client = SprayClient(
    api_key="sp_your_api_key",
    api_secret="your_api_secret"
)

# Store (ajouter des donnees)
result = client.store({"nom": "Jean Tremblay", "ville": "Quebec"})
spray_uuid = result["spray_uuid"]
print(f"Stocke: {spray_uuid}")

# Retrieve (recuperer des donnees)
data = client.retrieve(spray_uuid)
print(data)  # {'nom': 'Jean Tremblay', 'ville': 'Quebec'}

# Update (mettre a jour des donnees)
updated = client.update(spray_uuid, {"nom": "Jean Tremblay", "ville": "Montreal"})
new_uuid = updated["spray_uuid"]

# Delete (supprimer des donnees)
client.delete(new_uuid)

TypeScript / Node.js

Terminal
wget https://bytespray.com/sdks/spray-sdk-typescript-1.0.0.tar.gz
tar -xzf spray-sdk-typescript-1.0.0.tar.gz
cd spray-sdk-typescript
npm install && npm run build
TypeScript — Store, Retrieve, Update, Delete
import { SprayClient } from '@bytespray/spray-sdk';

const client = new SprayClient({
  apiKey: 'sp_your_api_key',
  apiSecret: 'your_api_secret'
});

// Store (ajouter des donnees)
const result = await client.store({ nom: 'Jean Tremblay', ville: 'Quebec' });
const sprayUuid = result.sprayUuid;
console.log('Stocke:', sprayUuid);

// Retrieve (recuperer des donnees)
const data = await client.retrieve(sprayUuid);
console.log(data); // { nom: 'Jean Tremblay', ville: 'Quebec' }

// Update (mettre a jour des donnees)
const updated = await client.update(sprayUuid, { nom: 'Jean Tremblay', ville: 'Montreal' });
const newUuid = updated.sprayUuid;

// Delete (supprimer des donnees)
await client.delete(newUuid);

Go

Terminal
wget https://bytespray.com/sdks/spray-sdk-go-1.0.0.tar.gz
tar -xzf spray-sdk-go-1.0.0.tar.gz
cd spray-sdk-go
Go — Store, Retrieve, Update, Delete
package main

import (
    "fmt"
    "log"

    spray "github.com/bytespray/spray-sdk-go"
)

func main() {
    client, err := spray.NewClient(
        "sp_your_api_key",
        "your_api_secret",
    )
    if err != nil {
        log.Fatal(err)
    }

    // Store (ajouter des donnees)
    result, err := client.Store(
        map[string]string{"nom": "Jean Tremblay", "ville": "Quebec"},
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Stocke:", result.SprayUUID)

    // Retrieve (recuperer des donnees)
    var data map[string]interface{}
    err = client.Retrieve(result.SprayUUID, &data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(data)

    // Update (mettre a jour des donnees)
    updated, err := client.Update(result.SprayUUID,
        map[string]string{"nom": "Jean Tremblay", "ville": "Montreal"}, nil)
    if err != nil {
        log.Fatal(err)
    }

    // Delete (supprimer des donnees)
    err = client.Delete(updated.SprayUUID)
    if err != nil {
        log.Fatal(err)
    }
}

PHP

Terminal
wget https://bytespray.com/sdks/spray-sdk-php-1.0.0.tar.gz
tar -xzf spray-sdk-php-1.0.0.tar.gz
cd spray-sdk-php
composer install
PHP — Store, Retrieve, Update, Delete
<?php
require_once 'vendor/autoload.php';

use ByteSpray\Spray\SprayClient;

$client = new SprayClient(
    'sp_your_api_key',
    'your_api_secret'
);

// Store (ajouter des donnees)
$result = $client->store(['nom' => 'Jean Tremblay', 'ville' => 'Quebec']);
$sprayUuid = $result['spray_uuid'];
echo "Stocke: " . $sprayUuid . "\n";

// Retrieve (recuperer des donnees)
$data = $client->retrieve($sprayUuid);
print_r($data);

// Update (mettre a jour des donnees)
$updated = $client->update(
    $sprayUuid,
    ['nom' => 'Jean Tremblay', 'ville' => 'Montreal']
);
$newUuid = $updated['spray_uuid'];

// Delete (supprimer des donnees)
$client->delete($newUuid);
Felicitations! Vos donnees sont stockees avec souverainete geographique. Elles resident uniquement dans les regions configurees dans votre namespace.

Authentication

All API requests require authentication using your namespace credentials via HTTP Basic Auth.

Credentials

Credential Format Description
api_key sp_xxxxxxxxxx Your namespace API key (public identifier)
api_secret 64 character hex string Your namespace API secret (keep this private!)

Using Credentials

Authentication Examples
# SDK - pass as constructor arguments
client = SprayClient(
    api_key="sp_a1b2c3d4e5f6g7h8",
    api_secret="your_api_secret_here"
)

# REST API - use HTTP Basic Auth (api_key:api_secret)
curl -u "sp_a1b2c3d4e5f6g7h8:your_api_secret_here" \
     https://api.bytespray.dev/v1/data
Security: Never expose your API secret in client-side code. Always use environment variables or secret management.

Namespaces

Namespaces define where your data is stored. Each namespace has its own credentials, region configuration, and RSA encryption key pair.

Creating a Namespace

  1. Go to the ByteSpray Dashboard
  2. Click "Create Namespace"
  3. Give it a name (e.g., "production-canada")
  4. Select the regions where data should be stored
  5. Copy your API key and secret (the secret is only shown once)

Region Selection

When you store data, it automatically goes to all regions configured in your namespace. You don't need to specify regions in your API calls - the namespace handles routing.

Example: Namespace with Canada/Quebec region
# Data automatically stored in Canada/Quebec nodes
result = client.store({"user": "John Doe"})

# No region parameter needed - namespace handles it

Data Sovereignty

The core feature of ByteSpray is the ability to control where your data physically resides.

How it works

  1. You create a namespace with specific regions (e.g., Canada/Quebec)
  2. When you call store(), data is routed only to nodes in those regions
  3. Data is encrypted, fragmented, and distributed across multiple nodes within the region
  4. No data ever leaves the specified regions

Available Regions

Country Locations
Canada Quebec, Ontario, British Columbia
United States Virginia, California, Texas
France Paris
Germany Frankfurt
Sweden Stockholm
United Kingdom London
Netherlands Amsterdam
Singapore Singapore
Japan Tokyo
Australia Sydney

Spray Algorithm

Your data isn't stored as a single file. It's fragmented and "sprayed" across multiple nodes.

How the Spray Algorithm Works:

  1. Encrypt: Data is encrypted with the namespace's RSA-2048 public key
  2. Fragment: Encrypted data is split into multiple blocks
  3. Distribute: Each block is sent to different nodes within the namespace's configured regions
  4. Replicate: Each block is stored on multiple nodes for redundancy

Benefits

  • No Single Point of Failure: Even if nodes go offline, data is recoverable
  • No Single Point of Breach: Compromising one node reveals nothing usable
  • Automatic Rebalancing: Network self-heals when nodes join/leave

Encryption

Each namespace has its own RSA-2048 key pair generated at creation time.

  • Public key: Stored in ByteSpray database, used to encrypt data before fragmentation
  • Private key: Stored in the Spray Network itself (encrypted with the owner's key), used only for data retrieval

This means ByteSpray cannot read your data - the private key is never stored in plaintext on our servers.

Store

Store data in the Spray Network. Returns a unique spray_uuid identifier.

REST API

POST /v1/data
curl -X POST https://api.bytespray.dev/v1/data \
  -u "sp_your_api_key:your_api_secret" \
  -H "Content-Type: application/json" \
  -d '{"data": "your data here", "content_type": "text"}'

# Response
{"spray_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}

Parameters

Parameter Type Required Description
data string | object Yes The data to store (JSON, text, or base64-encoded binary)
content_type string No Content type hint: "json", "text", or "binary"

SDK Example

Python
# Store a dictionary (automatically serialized to JSON)
result = client.store({"user": "John Doe", "email": "john@example.com"})
print(result["spray_uuid"])

# Store a string
result = client.store("Hello, World!")

# Store with metadata
result = client.store("sensitive data", metadata={"type": "medical"})

Retrieve

Retrieve previously stored data by its spray_uuid.

REST API

GET /v1/data/{spray_uuid}
curl https://api.bytespray.dev/v1/data/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -u "sp_your_api_key:your_api_secret"

# Response: the stored data

SDK Example

Python
data = client.retrieve("a1b2c3d4-e5f6-7890-abcd-ef1234567890")
print(data)

Update

Update previously stored data. This deletes the old data and stores the new data, returning a new spray_uuid.

REST API

PUT /v1/data/{spray_uuid}
curl -X PUT https://api.bytespray.dev/v1/data/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -u "sp_your_api_key:your_api_secret" \
  -H "Content-Type: application/json" \
  -d '{"data": "updated data", "content_type": "text"}'

# Response: new spray_uuid (old one is no longer valid)
{"spray_uuid": "new-uuid-here-..."}

SDK Example

Python
# Update returns a new spray_uuid
new_result = client.update(
    "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    {"user": "Jane Doe", "email": "jane@example.com"}
)
print(new_result["spray_uuid"])  # Use this new ID going forward
Important: Update returns a new spray_uuid. The old UUID is no longer valid after an update.

Delete

Permanently delete stored data from all nodes.

REST API

DELETE /v1/data/{spray_uuid}
curl -X DELETE https://api.bytespray.dev/v1/data/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -u "sp_your_api_key:your_api_secret"

SDK Example

Python
client.delete("a1b2c3d4-e5f6-7890-abcd-ef1234567890")
Warning: Deletion is permanent and cannot be undone.

Stats

Get usage statistics for your namespace.

Python
stats = client.get_stats()
print(stats)
# {'total_bytes_stored': 1048576, 'total_blocks': 42, 'total_requests': 150}

Regions

Get the list of regions configured for your namespace.

Python
regions = client.get_regions()
print(regions)
# [{'country': 'Canada', 'location': 'Quebec'}, {'country': 'France', 'location': 'Paris'}]

Python SDK

Installation

Terminal
pip install bytespray-sdk

Full Example

Python
from bytespray import SprayClient
import os

# Initialize from environment variables
client = SprayClient(
    api_key=os.environ["BYTESPRAY_API_KEY"],
    api_secret=os.environ["BYTESPRAY_API_SECRET"]
)

# Store data (dict, string, or bytes)
result = client.store({"version": "1.0", "config": "value"})
spray_uuid = result["spray_uuid"]
print(f"Stored: {spray_uuid}")

# Retrieve data
data = client.retrieve(spray_uuid)
print(data)

# Update data (returns new spray_uuid)
new_result = client.update(spray_uuid, {"version": "2.0"})
spray_uuid = new_result["spray_uuid"]

# Get usage statistics
stats = client.get_stats()
print(f"Total bytes: {stats['total_bytes_stored']}")

# Get namespace regions
regions = client.get_regions()
print(f"Regions: {regions}")

# Delete data
client.delete(spray_uuid)

TypeScript SDK

Installation

Terminal
npm install @bytespray/sdk

Full Example

TypeScript
import { SprayClient } from '@bytespray/sdk';

// Initialize the client
const client = new SprayClient({
  apiKey: process.env.BYTESPRAY_API_KEY!,
  apiSecret: process.env.BYTESPRAY_API_SECRET!
});

async function main() {
  // Store data
  const result = await client.store({ name: 'John Doe' });
  console.log('Stored:', result.sprayUuid);

  // Retrieve data
  const data = await client.retrieve(result.sprayUuid);
  console.log('Data:', data);

  // Update data (returns new sprayUuid)
  const updated = await client.update(
    result.sprayUuid,
    { name: 'Jane Doe' }
  );
  console.log('New ID:', updated.sprayUuid);

  // Get stats
  const stats = await client.getStats();
  console.log('Stats:', stats);

  // Get regions
  const regions = await client.getRegions();
  console.log('Regions:', regions);

  // Delete
  await client.delete(updated.sprayUuid);
}

main();

Go SDK

Installation

Terminal
go get github.com/bytespray/spray-sdk-go

Full Example

Go
package main

import (
    "fmt"
    "log"
    "os"

    spray "github.com/bytespray/spray-sdk-go"
)

func main() {
    // Initialize the client
    client, err := spray.NewClient(
        os.Getenv("BYTESPRAY_API_KEY"),
        os.Getenv("BYTESPRAY_API_SECRET"),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Store data
    result, err := client.Store(
        map[string]string{"name": "John Doe"},
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Stored:", result.SprayUUID)

    // Retrieve data
    var data map[string]interface{}
    err = client.Retrieve(result.SprayUUID, &data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Data:", data)

    // Update data
    updated, err := client.Update(
        result.SprayUUID,
        map[string]string{"name": "Jane Doe"},
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }

    // Get stats
    stats, _ := client.GetStats()
    fmt.Println("Stats:", stats)

    // Get regions
    regions, _ := client.GetRegions()
    fmt.Println("Regions:", regions)

    // Delete
    client.Delete(updated.SprayUUID)
}

PHP SDK

Installation

Terminal
composer require bytespray/spray-sdk

Full Example

PHP
<?php
require 'vendor/autoload.php';

use ByteSpray\Spray\SprayClient;

// Initialize the client
$client = new SprayClient(
    getenv('BYTESPRAY_API_KEY'),
    getenv('BYTESPRAY_API_SECRET')
);

// Store data
$result = $client->store(['name' => 'John Doe']);
echo "Stored: " . $result['spray_uuid'] . "\n";

// Retrieve data
$data = $client->retrieve($result['spray_uuid']);
print_r($data);

// Update data (returns new spray_uuid)
$updated = $client->update(
    $result['spray_uuid'],
    ['name' => 'Jane Doe']
);
echo "New ID: " . $updated['spray_uuid'] . "\n";

// Get stats
$stats = $client->getStats();
echo "Total bytes: " . $stats['total_bytes_stored'] . "\n";

// Get regions
$regions = $client->getRegions();
print_r($regions);

// Delete
$client->delete($updated['spray_uuid']);

Common Errors

Error Code Description
AuthenticationError 401 Invalid API key or secret
ForbiddenError 403 Namespace is inactive or disabled
NotFoundError 404 spray_uuid does not exist
ValidationError 400 Invalid request (missing data, payload too large)
RateLimitError 429 Too many requests (1000/hour per namespace)
ServerError 500 Internal error (Spray Network unavailable)

Rate Limits

API rate limits apply per namespace:

Plan Price Requests/hour Storage Namespaces
Free $0/mo 1,000 100 KB 2
Starter $9/mo 1,000 50 MB 3
Pro $29/mo 1,000 250 MB 5
Business $99/mo 1,000 2 GB 10
Enterprise $199/mo 1,000 10 GB 25
Scale $399/mo 1,000 20 GB 50
Rate limit headers: API responses include X-RateLimit-Remaining and Retry-After headers when approaching limits.

Need Help?