ByteSpray Documentation
Learn how to store and retrieve data with full control over geographic location.
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
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 .
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
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
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
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
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
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
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);
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
# 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
Namespaces
Namespaces define where your data is stored. Each namespace has its own credentials, region configuration, and RSA encryption key pair.
Creating a Namespace
- Go to the ByteSpray Dashboard
- Click "Create Namespace"
- Give it a name (e.g., "production-canada")
- Select the regions where data should be stored
- 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.
# 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
- You create a namespace with specific regions (e.g., Canada/Quebec)
- When you call
store(), data is routed only to nodes in those regions - Data is encrypted, fragmented, and distributed across multiple nodes within the region
- 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:
- Encrypt: Data is encrypted with the namespace's RSA-2048 public key
- Fragment: Encrypted data is split into multiple blocks
- Distribute: Each block is sent to different nodes within the namespace's configured regions
- 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
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
# 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
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
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
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
# 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
spray_uuid. The old UUID is no longer valid after an update.
Delete
Permanently delete stored data from all nodes.
REST API
curl -X DELETE https://api.bytespray.dev/v1/data/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-u "sp_your_api_key:your_api_secret"
SDK Example
client.delete("a1b2c3d4-e5f6-7890-abcd-ef1234567890")
Stats
Get usage statistics for your namespace.
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.
regions = client.get_regions()
print(regions)
# [{'country': 'Canada', 'location': 'Quebec'}, {'country': 'France', 'location': 'Paris'}]
Python SDK
Installation
pip install bytespray-sdk
Full Example
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
npm install @bytespray/sdk
Full Example
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
go get github.com/bytespray/spray-sdk-go
Full Example
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
composer require bytespray/spray-sdk
Full Example
<?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 |
X-RateLimit-Remaining and Retry-After headers when approaching limits.