BurnOnRead Documentation

Complete guide to secure, ephemeral secret sharing with BurnOnRead.

Quick Start: No API key required to create secrets via the web interface. Pro users get API access for programmatic integration.

What is BurnOnRead?

BurnOnRead is a secure platform for sharing sensitive information that automatically self-destructs after being viewed. Perfect for sharing passwords, API keys, credentials, and confidential data.

Key Features

  • Self-Destructing Secrets: Automatically deleted after viewing
  • AES-256 Encryption: Military-grade encryption at rest
  • Password Protection: Optional additional security layer
  • Real-Time Notifications: Know when secrets are viewed (Pro)
  • Dropzone Requests: Request secrets from others (Pro)
  • REST API: Programmatic access for integrations (Pro)

Web Interface

Creating a Secret

  1. Go to the homepage
  2. Paste your sensitive text into the form
  3. Optionally add a password for extra security
  4. Click "Create Secure Link"
  5. Copy the generated link and share it with your recipient
Important: Anonymous secrets expire in 15 minutes. Register for free to extend expiration up to 60 minutes.

Viewing a Secret

  1. Click the secret link (format: /s/<secret_id>)
  2. If password-protected, enter the password
  3. View the secret (shown once only)
  4. Secret is immediately and permanently deleted

Dropzones (Pro Feature)

Dropzones allow you to request secrets from others:

  1. Go to your dashboard
  2. Create a new dropzone with a label (e.g., "Database Password")
  3. Share the dropzone link with your recipient
  4. Recipient fills the dropzone with the secret
  5. You retrieve and view the secret once from your dashboard

API Overview

Integrate BurnOnRead into your applications with our REST API.

Pro Feature: API access requires a Pro account (one-time $29 lifetime license). Sign up free and upgrade to unlock API access.

Base URL

https://burnonread.com

Response Format

All API responses are in JSON format.

Error Handling

The API uses standard HTTP status codes:

  • 200 - Success
  • 400 - Bad Request (invalid parameters)
  • 401 - Unauthorized (invalid or missing API key)
  • 404 - Not Found (secret doesn't exist or expired)
  • 429 - Too Many Requests (rate limit exceeded)
  • 500 - Internal Server Error

Authentication

Getting Your API Key

  1. Sign up for a free account
  2. Upgrade to Pro (one-time $29 payment for lifetime access)
  3. Go to your dashboard
  4. Click "Generate API Key"
  5. Copy and securely store your API key
Security Warning: Never commit API keys to version control or expose them in client-side code. Treat API keys like passwords.

Using Your API Key

Include your API key in the X-API-KEY header:

curl -H "X-API-KEY: sk_yourapikey123..." \
     -d '{"secret_text":"my secret"}' \
     https://burnonread.com/create

Create Secret API

Endpoint

POST /create

Request Headers

Content-Type: application/json
X-API-KEY: sk_yourapikey123...

Request Body

Parameter Type Required Description
secret_text string Yes The secret message to encrypt and store
password string No Optional password protection
duration integer No Expiration time in minutes (15-60 for Pro, 15 for free). Default: 60

Example Request

{
  "secret_text": "Database password: MyS3cur3P@ss!",
  "password": "optional_password",
  "duration": 30
}

Success Response (200 OK)

{
  "secret_id": "abc123def456",
  "link": "https://burnonread.com/s/abc123def456",
  "expires_in_minutes": 30
}

Error Response (400 Bad Request)

{
  "error": "secret_text is required"
}

Full Example (cURL)

curl -X POST https://burnonread.com/create \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: sk_yourapikey123..." \
  -d '{
    "secret_text": "Database password: MyS3cur3P@ss!",
    "password": "optional_password",
    "duration": 30
  }'

Dropzones API (Pro)

Create Dropzone

POST /app/dropzone

Create a secure dropzone to request secrets from others.

Request Headers

Content-Type: application/json
X-API-KEY: sk_yourapikey123...

Request Body

Parameter Type Required Description
requester_email string Yes Email of person filling the dropzone
label string Yes Description (e.g., "Database Password")

Success Response (200 OK)

{
  "dropzone_id": "xyz789abc123",
  "link": "https://burnonread.com/d/xyz789abc123",
  "label": "Database Password",
  "expires_in_hours": 24
}

Retrieve Dropzone Secret

POST /dropzone/reveal/<dropzone_id>

Retrieve and delete the secret from a filled dropzone.

Success Response (200 OK)

{
  "secret": "The decrypted secret text",
  "filled_at": "2025-01-15T14:30:00Z"
}
Note: The dropzone secret is deleted immediately after retrieval, just like regular secrets.

Code Examples

Python

import requests
import json

API_KEY = "sk_yourapikey123..."
BASE_URL = "https://burnonread.com"

def create_secret(text, password=None, duration=60):
    """Create a self-destructing secret"""
    headers = {
        "Content-Type": "application/json",
        "X-API-KEY": API_KEY
    }

    data = {
        "secret_text": text,
        "duration": duration
    }

    if password:
        data["password"] = password

    response = requests.post(
        f"{BASE_URL}/create",
        headers=headers,
        json=data
    )

    if response.status_code == 200:
        result = response.json()
        return result["link"]
    else:
        raise Exception(f"Error: {response.text}")

# Usage
link = create_secret(
    "Database password: MyS3cur3P@ss!",
    password="optional_password",
    duration=30
)
print(f"Secret link: {link}")

JavaScript (Node.js)

const axios = require('axios');

const API_KEY = 'sk_yourapikey123...';
const BASE_URL = 'https://burnonread.com';

async function createSecret(text, password = null, duration = 60) {
  try {
    const response = await axios.post(
      `${BASE_URL}/create`,
      {
        secret_text: text,
        password: password,
        duration: duration
      },
      {
        headers: {
          'Content-Type': 'application/json',
          'X-API-KEY': API_KEY
        }
      }
    );

    return response.data.link;
  } catch (error) {
    console.error('Error creating secret:', error.response.data);
    throw error;
  }
}

// Usage
createSecret('Database password: MyS3cur3P@ss!', 'optional_password', 30)
  .then(link => console.log(`Secret link: ${link}`))
  .catch(err => console.error(err));

PHP

<?php
$apiKey = 'sk_yourapikey123...';
$baseUrl = 'https://burnonread.com';

function createSecret($text, $password = null, $duration = 60) {
    global $apiKey, $baseUrl;

    $data = [
        'secret_text' => $text,
        'duration' => $duration
    ];

    if ($password) {
        $data['password'] = $password;
    }

    $ch = curl_init("$baseUrl/create");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        "X-API-KEY: $apiKey"
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode === 200) {
        $result = json_decode($response, true);
        return $result['link'];
    } else {
        throw new Exception("Error: $response");
    }
}

// Usage
$link = createSecret(
    'Database password: MyS3cur3P@ss!',
    'optional_password',
    30
);
echo "Secret link: $link\n";
?>

Bash (cURL)

#!/bin/bash

API_KEY="sk_yourapikey123..."
BASE_URL="https://burnonread.com"

# Create a secret
create_secret() {
    local secret_text="$1"
    local password="${2:-}"
    local duration="${3:-60}"

    local data="{\"secret_text\":\"$secret_text\",\"duration\":$duration"

    if [ -n "$password" ]; then
        data="$data,\"password\":\"$password\""
    fi

    data="$data}"

    curl -X POST "$BASE_URL/create" \
        -H "Content-Type: application/json" \
        -H "X-API-KEY: $API_KEY" \
        -d "$data" \
        | jq -r '.link'
}

# Usage
LINK=$(create_secret "Database password: MyS3cur3P@ss!" "optional_password" 30)
echo "Secret link: $LINK"

Go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

const (
    APIKey  = "sk_yourapikey123..."
    BaseURL = "https://burnonread.com"
)

type SecretRequest struct {
    SecretText string `json:"secret_text"`
    Password   string `json:"password,omitempty"`
    Duration   int    `json:"duration"`
}

type SecretResponse struct {
    SecretID         string `json:"secret_id"`
    Link             string `json:"link"`
    ExpiresInMinutes int    `json:"expires_in_minutes"`
}

func createSecret(text, password string, duration int) (string, error) {
    req := SecretRequest{
        SecretText: text,
        Password:   password,
        Duration:   duration,
    }

    jsonData, err := json.Marshal(req)
    if err != nil {
        return "", err
    }

    httpReq, err := http.NewRequest("POST", BaseURL+"/create", bytes.NewBuffer(jsonData))
    if err != nil {
        return "", err
    }

    httpReq.Header.Set("Content-Type", "application/json")
    httpReq.Header.Set("X-API-KEY", APIKey)

    client := &http.Client{}
    resp, err := client.Do(httpReq)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)

    if resp.StatusCode != 200 {
        return "", fmt.Errorf("error: %s", string(body))
    }

    var result SecretResponse
    if err := json.Unmarshal(body, &result); err != nil {
        return "", err
    }

    return result.Link, nil
}

func main() {
    link, err := createSecret("Database password: MyS3cur3P@ss!", "optional_password", 30)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Println("Secret link:", link)
}

Security

Encryption

BurnOnRead uses AES-256-GCM encryption to protect secrets at rest:

  • Algorithm: AES-256-GCM (Advanced Encryption Standard with Galois/Counter Mode)
  • Key Size: 256 bits (same standard used by NSA for top-secret data)
  • Authentication: Built-in authentication tags prevent tampering
  • Nonce: Unique 12-byte nonce for each secret

Data Lifecycle

  1. Creation: Secret is encrypted immediately upon submission
  2. Storage: Only encrypted data stored in database
  3. Transmission: HTTPS/TLS for all data in transit
  4. Viewing: Decrypted in memory for display
  5. Destruction: Permanent deletion from database immediately after viewing

What We Cannot Do

  • ❌ Recover deleted secrets (they're permanently gone)
  • ❌ View secret content (we don't store decryption keys separately)
  • ❌ Restore expired secrets (janitor permanently deletes them)
  • ❌ Prevent screenshot/copying (once viewed, recipient has access)

Best Practices

  • ✅ Always use HTTPS in production
  • ✅ Add password protection for highly sensitive secrets
  • ✅ Use shortest possible expiration time
  • ✅ Verify recipient before sharing links
  • ✅ Communicate password separately (e.g., phone call)
  • ✅ Rotate API keys regularly
  • ✅ Never log API keys or secret content

Best Practices

For Sharing Secrets

✅ DO
  • Use password protection for highly sensitive data
  • Set the shortest expiration time needed
  • Verify the recipient before sharing the link
  • Send password via separate channel (phone, Slack DM)
  • Notify recipient when you've shared a secret
  • Use descriptive dropzone labels
❌ DON'T
  • Share secret links in public channels
  • Send password and link together in same message
  • Assume secrets survive past expiration
  • Share the same secret link multiple times
  • Use for permanent storage (secrets are ephemeral)
  • Share API keys in client-side code

For API Integration

  • Store API keys in environment variables, not code
  • Use separate API keys for development and production
  • Implement rate limiting in your application
  • Log API errors but never log secret content
  • Handle errors gracefully (network failures, rate limits)
  • Implement retry logic with exponential backoff

Example: Secure Secret Sharing Workflow

1. Create password-protected secret via API
2. Send link to recipient via Slack
3. Call recipient to provide password
4. Recipient views secret
5. You receive real-time notification
6. Secret is automatically deleted

Developer FAQ

Can I create secrets without an API key?

Yes, anyone can create secrets via the web interface without an account. However, API access requires a Pro account (one-time $29 lifetime license).

What's the rate limit for API requests?

API endpoints are rate-limited to prevent abuse. If you hit the limit, you'll receive a 429 Too Many Requests response. Wait and retry with exponential backoff.

Can I retrieve a secret via API?

Secrets can only be viewed once via their unique URL (/s/<secret_id>). The API is for creation, not retrieval, to maintain security.

What happens if I regenerate my API key?

Your old API key is immediately invalidated. Update all integrations with the new key to avoid authentication errors.

Where does BurnOnRead run?

BurnOnRead is provided as a hosted service with distributed POPs in New York City, San Francisco, and Frankfurt — with more coming online as we scale.

How do I report a security vulnerability?

Please email security issues to security@burnonread.com. We take security seriously and will respond promptly.

Need Help?

Can't find what you're looking for? Contact support or file a support request.