Info / API
Security
Your security and privacy are our top priorities. Here’s how we protect your data:
- Server-Side Encryption: All files are encrypted on our servers. We use a sophisticated system of private and public keys to ensure that your data is secure. All key management and decryption are also handled on the server-side.
- How it Works:
- Your user key seed is sent to the server, which then derives a public key.
- The public key is used to access your user-specific database, which contains the encrypted file key seeds.
- These file key seeds resolve to public keys that are used to decrypt the file's metadata and the list of its chunks.
- This chunk list contains another set of seeds, which resolve to public keys that decrypt the actual file chunks at their respective storage addresses.
- IP Protection: We use a proxy service to mask your IP address, adding another layer of privacy.
Legal & Information
- Disclaimer
- Terms of Service
- Privacy Policy
- Content Policy and DMCA Information
- Imprint
- Recreate Decryption Key
- Erasure Coding (EC 14+4) Explained
API Documentation
Register a new user
To get a new user key, you can make a GET request to /register. This will return a page with your new key.
Get file list
To get a list of your uploaded files, make a GET request to /files?key=YOUR_KEY.
Direct Upload
To upload a file directly, send a POST request to /upload?key=YOUR_KEY with the file in a form field named 'file'.
Remote Upload
To upload a file from a URL, make a GET request to /remoteuploadurl?key=YOUR_KEY&url=FILE_URL&filename=FILENAME.
Chunked Upload
For large files, you can use chunked uploading.
- Initiate Upload: GET
/initiateupload?key=YOUR_KEY&filename=FILENAME. This will return a session hash. - Upload Chunks: POST chunks to
/uploadchunk?session_hash=SESSION_HASHwith the chunk in a form field named 'file'. - End Upload: GET
/endupload?session_hash=SESSION_HASHto finalize the upload.
Delete File
To delete a file, send a POST request to /delete/FILE_ID?key=YOUR_KEY.
Edit File
To edit a file's metadata, you first need to get the edit page with a GET request to /edit/FILE_ID?key=YOUR_KEY. Then, you can send a POST request to /editform/FILE_ID?key=YOUR_KEY with a JSON body containing the new metadata (name, isPublic, thumbnail, note).
Checkout API (Accept Payments)
Send a customer to a hosted checkout page. They can pay in any supported currency; once enough has been received, AnonDrop sends your server a signed confirmation you can verify with the public key below.
1. Send the customer to checkout
Redirect the buyer to a GET URL:
https://anondrop.net/checkout
?wallet=YOUR_WALLET_KEY
&nonce=UNIQUE_ORDER_ID
&amount=AMOUNT_IN_SOL
&shop=Your%20Shop
&product=Product%20Name
&details=Short%20description
&message=Optional%20note
&image=https://yoursite.com/item.png
&callback=https://yoursite.com/anondrop-callback
wallet— your wallet key (funds are credited here).nonce— a unique order id you choose. A nonce can only be used once per wallet and can only be completed once.amount— the amount you require, in SOL.image— product image, .png or .webp only.callback— your URL; we POST the signed confirmation here when the order is paid.
2. Receive the signed callback
When the order is fully paid we POST this JSON to your callback URL (and the same is available by polling /checkoutstatus/WALLET/NONCE):
{
"payload": {
"wallet": "YOUR_WALLET_KEY",
"nonce": "UNIQUE_ORDER_ID",
"amount_requested": "1.5",
"amount_paid": "1.5",
"currency": "SOL",
"currencies_paid": ["BTC"],
"status": "paid",
"paid_at": 1700000000
},
"signature": "<base64 ed25519 signature>",
"public_key": "<base64 public key>",
"algorithm": "ed25519"
}
3. Public key (verify everything against this)
Ed25519 public key — also available as JSON at /checkoutpubkey:
4. Verify the callback
Always verify the signature, then check the fields match what you expect. The signature is over the canonical JSON of payload (keys sorted, no spaces). Do not trust any value that is not inside the signed payload.
Python (PyNaCl):
import base64, json
from nacl.signing import VerifyKey
PUBLIC_KEY_B64 = "V7F6+hiMHqB5i/csaZ1yFqDXbP7qGcBZ/LLnJi8rj0k="
def verify(body, expected_wallet, expected_nonce, expected_amount):
payload = body["payload"]
msg = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode()
VerifyKey(base64.b64decode(PUBLIC_KEY_B64)).verify(
msg, base64.b64decode(body["signature"])) # raises if invalid
# bind to YOUR order - a customer cannot change these by editing the URL
assert payload["wallet"] == expected_wallet
assert payload["nonce"] == expected_nonce
assert payload["status"] == "paid"
assert float(payload["amount_paid"]) >= float(expected_amount)
return True
Node.js (tweetnacl):
const nacl = require("tweetnacl");
const PUBLIC_KEY_B64 = "V7F6+hiMHqB5i/csaZ1yFqDXbP7qGcBZ/LLnJi8rj0k=";
function verify(body, expectedWallet, expectedNonce, expectedAmount) {
const p = body.payload;
const msg = Buffer.from(JSON.stringify(sortKeys(p))); // sorted keys, no spaces
const ok = nacl.sign.detached.verify(
msg,
Buffer.from(body.signature, "base64"),
Buffer.from(PUBLIC_KEY_B64, "base64")
);
if (!ok) throw new Error("bad signature");
if (p.wallet !== expectedWallet) throw new Error("wrong wallet");
if (p.nonce !== expectedNonce) throw new Error("wrong nonce");
if (p.status !== "paid") throw new Error("not paid");
if (parseFloat(p.amount_paid) < parseFloat(expectedAmount)) throw new Error("underpaid");
return true;
}
// sortKeys: rebuild the object with keys sorted so JSON.stringify is canonical
function sortKeys(o){ return Object.keys(o).sort().reduce((a,k)=>(a[k]=o[k],a),{}); }
Why each check matters: the signature proves AnonDrop produced the message (not a customer). Checking wallet and nonce ties it to your order — a customer who edits the checkout URL cannot make us sign a different wallet or reuse a nonce. Checking amount_paid >= amount_requested confirms they actually paid enough.