Retrieve your transfers and statistics programmatically, and get a notification the moment someone downloads your files. Read-only REST + HMAC-signed webhooks.
Create an API key on your account page(part of every paid plan). The key is shown only once — keep it safe. Send it with every request:
Authorization: Bearer dlk_live_xxxxxxxxxxxxxxxxxxxx
Base URL:https://downloadlink.nl/api/v1. All responses are JSON and limited to your own account.
Account + storage usage.
curl -H "Authorization: Bearer dlk_live_xxx" \
https://downloadlink.nl/api/v1/me
{
"email": "jij@bedrijf.nl",
"is_trial": false,
"plan": "100 GB",
"storage": { "used_bytes": 5242880, "quota_bytes": 107374182400, "percent": 0 }
}
Your transfers (newest first). Parameter ?limit=(1–200, default 50).
{ "count": 1, "transfers": [ { "token": "a1b2c3d4e5f6a7b8", "title": "Quote Q3", "created_at": "2026-06-17T09:12:00+00:00", "expires_at": "2026-06-24T09:12:00+00:00", "unlimited": false, "revoked": false, "files": 3, "size_bytes": 8412300, "downloads": 2, "recipients": 1, "url": "https://downloadlink.nl/p/a1b2c3d4e5f6a7b8" } ] }
A single transfer: metadata, the files, and recent download activity (who/when/which file).
{ "token": "a1b2c3d4e5f6a7b8", "title": "Quotation Q3", "created_at": "2026-06-17T09:12:00+00:00", "expires_at": "2026-06-24T09:12:00+00:00", "unlimited": false, "revoked": false, "max_downloads": null, "downloads_used": 0, "size_bytes": 8412300, "files": [ { "name": "quotation.pdf", "size_bytes": 412300 } ], "downloads": 2, "url": "https://downloadlink.nl/p/a1b2c3d4e5f6a7b8", "activity": [ { "downloaded_at": "2026-06-17T10:30:00+00:00", "type": "zip", "file": "(whole package / zip)", "ip": "203.0.113.7" }, { "downloaded_at": "2026-06-17T09:58:00+00:00", "type": "file", "file": "quotation.pdf", "ip": "198.51.100.24" } ] }
Note: ip is the full IP address of the person who downloaded — personal data of your recipient, not an anonymised figure. You receive it in full, just as in the activity overview, the downloads CSV and the proof of delivery (PDF); it is there so you can demonstrate that a package has been retrieved. If you process or store it in your own system, include it in your own privacy statement. We return the 100 most recent records; downloads counts those records. We keep them for a maximum of 12 months — after that, they can no longer be retrieved, not even via the API. downloads_used is the counter for the download limit and remains 0 as long as max_downloads is empty.
Rate limit: 120 requests per minute per key (HTTP 429 when exceeded).
Deliver a file via your own branded download page, straight from your system — a generated report or invoice, for example:
curl -X POST https://downloadlink.nl/api/v1/transfers -H "Authorization: Bearer <sleutel>" -F "file=@rapport.pdf" -F "title=Rapport week 30" -F "expiry_days=30" # of 'never' voor onbeperkt geldig # optioneel: -F "password=geheim" voor een wachtwoord op de downloadpagina
HTTP 201 { "ok": true, "token": "a1b2c3d4e5f6a7b8", "url": "https://downloadlink.nl/p/a1b2c3d4e5f6a7b8", "expires_at": "2026-08-22T10:30:00+00:00", "unlimited": false }
Error paths:402 payment_required(the write API is part of the paid plans),402 quota_exceeded(storage full),413(file larger than the API limit — use the upload page for that). The download page branding follows the account the key belongs to.
Register an https-URL on your account page(the "Test" button immediately sends aping-event so you can check your integration). As soon as someone downloads your transfer, we send a POST with this event:
POST https://jouw-server.nl/webhooks/downloadlink
X-Downloadlink-Event: transfer.downloaded
X-Downloadlink-Signature: sha256=<hmac>
Content-Type: application/json
{
"event": "transfer.downloaded",
"delivered_at": "2026-06-17T10:30:00+00:00",
"data": {
"token": "a1b2c3d4e5f6a7b8",
"title": "Offerte Q3",
"url": "https://downloadlink.nl/p/a1b2c3d4e5f6a7b8",
"download_type": "zip",
"downloaded_at": "2026-06-17T10:30:00+00:00"
}
}
Compute HMAC-SHA256 over the raw request body with your webhook secret and compare it constant-time against the header. Ignore messages that do not match.
Python
import hmac, hashlib
def is_valid(secret: str, raw_body: bytes, header: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header or "")
Node.js
const crypto = require('crypto');
function isValid(secret, rawBody, header) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(expected), b = Buffer.from(header || '');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Reply with HTTP 2xx to confirm delivery. After 15 failed attempts we switch the webhook off; a successful test (button on your account page) turns it back on. Only public https URLs are allowed.