Back to homepage

API & Webhooks

Retrieve your transfers and statistics programmatically, and get a notification the moment someone downloads your files. Read-only REST + HMAC-signed webhooks.

1. Getting started

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

2. Endpoints

Base URL:https://downloadlink.nl/api/v1. All responses are JSON and limited to your own account.

GET/api/v1/me

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 }
}

GET/api/v1/transfers

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" } ] }

GET /api/v1/transfers/<token>

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).

2b. Creating a transfer (write)

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.

3. Webhooks

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"
  }
}

Verifying the signature

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.