voidnote — Official Rust SDK
Zero-knowledge self-destructing notes and live encrypted streams. The key lives in the link. We never see it.
Install
[]
= "0.1"
Or with Cargo:
Quick start
Read a note
use read;
let note = read.await?;
println!;
println!;
println!;
Create a note
use ;
let note = create
.await?;
println!;
println!;
Live encrypted stream
use ;
use StreamExt;
let mut stream = create_stream
.await?;
println!;
stream.write.await?;
stream.write.await?;
stream.write.await?;
stream.close.await?;
Watch a stream (SSE)
use StreamExt;
let mut events = stream.watch;
while let Some = events.next.await
Blocking API
For use in synchronous contexts (scripts, CLI tools, non-async code):
use blocking;
let note = read?;
println!;
let created = create?;
println!;
API reference
async fn read(url_or_token: &str) -> Result<ReadResult>
Reads a note. Accepts either a full URL (https://voidnote.net/note/<token>) or a raw 64-character hex token.
ReadResult
| Field | Type | Description |
|---|---|---|
content |
String |
Decrypted plaintext |
title |
Option<String> |
Note title if set |
view_count |
u32 |
How many times read |
max_views |
u32 |
Destruction threshold |
destroyed |
bool |
Whether the note is gone |
async fn create(content: &str, opts: CreateOptions) -> Result<CreateResult>
Creates a self-destructing encrypted note.
CreateOptions
| Field | Type | Default | Description |
|---|---|---|---|
api_key |
String |
required | Your VoidNote API key |
title |
Option<String> |
None |
Optional title (stored encrypted) |
max_views |
Option<u32> |
None |
Destroy after N reads |
ttl_minutes |
Option<u32> |
None |
Expire after N minutes |
CreateResult
| Field | Type | Description |
|---|---|---|
url |
String |
Shareable URL (contains key in fragment) |
expires_at |
String |
ISO 8601 expiry timestamp |
async fn create_stream(opts: StreamOptions) -> Result<StreamHandle>
Opens a live encrypted stream. Returns a handle for writing.
StreamOptions
| Field | Type | Default | Description |
|---|---|---|---|
api_key |
String |
required | Your VoidNote API key |
title |
Option<String> |
None |
Stream title |
max_views |
Option<u32> |
None |
Limit concurrent watchers |
ttl_minutes |
Option<u32> |
None |
Auto-close after N minutes |
StreamHandle
| Method | Description |
|---|---|
.url |
Shareable URL for the stream |
async fn write(&mut self, msg: &str) |
Encrypt and send a message |
async fn close(&mut self) |
Close the stream |
fn watch(&self) -> impl Stream<Item = Result<String>> |
Subscribe to live messages (SSE) |
Security model
VoidNote uses zero-knowledge encryption — the server never sees your plaintext.
- A random 32-byte token is generated client-side
- The first 16 bytes become the
tokenId(sent to the server as a lookup key) - The last 16 bytes become the
secret— used to derive an AES-256-GCM key via SHA-256 - Content is encrypted locally before upload
- The full 64-character hex token is embedded in the URL fragment (
#token) — fragments are never sent to servers - Anyone with the link can decrypt; without the link, the server cannot
Error handling
use ;
match read.await
Error variants
| Variant | Meaning |
|---|---|
NotFound |
404 — note gone or never existed |
Unauthorized |
401 — invalid API key |
Api(String) |
Other HTTP error with message |
DecryptionFailed |
Ciphertext tampered or wrong key |
Network(reqwest::Error) |
HTTP transport error |
Json(serde_json::Error) |
Unexpected response format |
Hex(hex::FromHexError) |
Invalid token format |
Run the demo
# Read a note
# Create a note
# Open a stream
License
MIT