Export Data
Export all journal data as JSON for backup or portability.
curl http://127.0.0.1:5000/api/export > backup.json
{
"entries": {
"2024-03-15": {
"text": "Today was productive...",
"photos": [],
"tags": ["work"],
"sentiment": {
"compound": 0.742,
"mood": "positive",
"scores": {
"positive": 0.352,
"negative": 0.021,
"neutral": 0.627
}
},
"themes": ["work", "productivity"],
"word_count": 47,
"updatedAt": "2024-03-15T14:30:22.123Z"
},
"2024-03-14": {
"text": "Quiet day at home...",
"photos": [],
"tags": [],
"sentiment": {...},
"themes": ["alone_time"],
"word_count": 23,
"updatedAt": "2024-03-14T19:15:10.456Z"
}
},
"metadata": {
"created_at": "2024-01-01T00:00:00.000Z"
},
"exported_at": "2024-03-16T10:30:45.789Z",
"version": "1.0"
}
Response Fields
All journal entries, keyed by date (YYYY-MM-DD)
Journal metadata (creation date, etc.)
ISO 8601 timestamp of export
Export format version (currently “1.0”)
Import Data
Restore journal data from a backup file.
This will replace all existing data. Make sure you have a current backup before importing.
curl -X POST http://127.0.0.1:5000/api/import \
-H "Content-Type: application/json" \
-d @backup.json
Request Body
Must be a valid export JSON with at minimum:
Dictionary of journal entries keyed by date
Journal metadata (will be preserved)
Response
{
"imported": true,
"entries_count": 45
}
Whether import was successful
Number of entries imported
The import adds a timestamp to metadata:
{
"metadata": {
"created_at": "2024-01-01T00:00:00.000Z",
"imported_at": "2024-03-16T10:35:20.123Z"
}
}
Clear All Data
Delete all journal data (irreversible).
This action cannot be undone. Export a backup first!
curl -X DELETE http://127.0.0.1:5000/api/clear
Whether data was successfully cleared
Backup Best Practices
Regular Backups
Create a scheduled backup script:
#!/bin/bash
# backup-journal.sh
DATE=$(date +%Y-%m-%d)
BACKUP_DIR="$HOME/journal-backups"
mkdir -p "$BACKUP_DIR"
curl http://127.0.0.1:5000/api/export > "$BACKUP_DIR/journal-backup-$DATE.json"
echo "Backup saved to $BACKUP_DIR/journal-backup-$DATE.json"
# Keep only last 30 days
find "$BACKUP_DIR" -name "journal-backup-*.json" -mtime +30 -delete
Schedule with cron:
# Run daily at 11 PM
0 23 * * * /path/to/backup-journal.sh
Encrypted Backups
Encrypt sensitive backup files:
# Export and encrypt
curl http://127.0.0.1:5000/api/export | \
openssl enc -aes-256-cbc -salt -pbkdf2 > journal-backup-encrypted.json.enc
# Decrypt and import
openssl enc -aes-256-cbc -d -pbkdf2 -in journal-backup-encrypted.json.enc | \
curl -X POST http://127.0.0.1:5000/api/import \
-H "Content-Type: application/json" \
-d @-
Cloud Storage (Optional)
Only use encrypted cloud storage for journal backups.
import requests
import json
from datetime import datetime
import boto3 # AWS S3 example
# Export
data = requests.get('http://127.0.0.1:5000/api/export').json()
filename = f"journal-backup-{datetime.now().strftime('%Y-%m-%d')}.json"
# Encrypt and upload to S3
s3 = boto3.client('s3')
s3.put_object(
Bucket='my-journal-backups',
Key=filename,
Body=json.dumps(data),
ServerSideEncryption='AES256'
)
Version Control
Track journal history with Git:
# Initialize repo
git init journal-backup
cd journal-backup
# Daily backup script
curl http://127.0.0.1:5000/api/export > journal.json
git add journal.json
git commit -m "Backup $(date +%Y-%m-%d)"
# View history
git log --oneline journal.json
# Restore old version
git checkout <commit-hash> journal.json
curl -X POST http://127.0.0.1:5000/api/import \
-H "Content-Type: application/json" \
-d @journal.json
Migration Between Devices
Device A (Export)
# Export from Device A
curl http://127.0.0.1:5000/api/export > journal-export.json
# Transfer via USB, email, or secure file sharing
Device B (Import)
# Import on Device B
curl -X POST http://127.0.0.1:5000/api/import \
-H "Content-Type: application/json" \
-d @journal-export.json
Exported data is standard JSON:
- Human-readable: Open in any text editor
- Portable: Import to other systems
- Scriptable: Process with Python, Node.js, jq, etc.
- No vendor lock-in: Own your data forever
Example Processing
# Count entries
jq '.entries | length' backup.json
# Extract all text
jq '.entries[].text' backup.json
# Filter by mood
jq '.entries | to_entries | map(select(.value.sentiment.mood == "positive"))' backup.json
# Get date range
jq '.entries | keys | [first, last]' backup.json
Error Handling
{
"error": "Invalid data format"
}
HTTP Status: 400
Missing Entries Field
{
"error": "Missing 'entries' field"
}
HTTP Status: 400
Save Failure
{
"error": "Failed to save imported data"
}
HTTP Status: 500
Security Considerations
Backup files contain your unencrypted journal entries. Handle with care.
Protect Backup Files
- Encrypt at rest: Use encrypted drives or file encryption
- Secure permissions:
chmod 600 backup.json (user-only access)
- Delete old backups: Don’t accumulate unnecessary copies
- Secure transfer: Use encrypted channels (SSH, HTTPS, encrypted USB)
Don’t:
❌ Email backups unencrypted
❌ Store in public cloud without encryption
❌ Share backup files with others
❌ Leave backups on shared/public computers
Automated Backup UI
Example backup interface:
<div class="backup-section">
<h2>Backup & Restore</h2>
<!-- Export -->
<button onclick="exportData()">💾 Export Backup</button>
<!-- Import -->
<input type="file" id="import-file" accept=".json" />
<button onclick="importData()">📥 Import Backup</button>
<!-- Clear -->
<button onclick="clearData()" class="danger">
⚠️ Clear All Data
</button>
</div>
<script>
function exportData() {
fetch('http://127.0.0.1:5000/api/export')
.then(r => r.json())
.then(data => {
const blob = new Blob([JSON.stringify(data, null, 2)],
{ type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `journal-${new Date().toISOString().split('T')[0]}.json`;
a.click();
});
}
function importData() {
const file = document.getElementById('import-file').files[0];
if (!file) return;
file.text().then(text => {
return fetch('http://127.0.0.1:5000/api/import', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: text
});
})
.then(r => r.json())
.then(result => {
if (result.imported) {
alert(`Imported ${result.entries_count} entries!`);
location.reload();
}
});
}
function clearData() {
if (!confirm('Delete all data? This cannot be undone!')) return;
fetch('http://127.0.0.1:5000/api/clear', { method: 'DELETE' })
.then(r => r.json())
.then(result => {
if (result.cleared) {
alert('All data deleted.');
location.reload();
}
});
}
</script>
Next Steps
Data Storage
Learn about local JSON storage
API Overview
Explore other API endpoints