API & Webhooks

Récupérez vos transferts et statistiques par programme, créez des transferts depuis votre propre système et soyez averti dès que quelqu'un télécharge vos fichiers. API REST avec des autorisations par clé + webhooks signés HMAC.

1. Pour commencer

Créez une clé API sur votre page de compte (inclus dans chaque formule payante). La clé n'est affichée qu'une seule fois — conservez-la en lieu sûr. Envoyez-la avec chaque requête :

Authorization: Bearer dlk_live_xxxxxxxxxxxxxxxxxxxx

Autorisations et date d'expiration

Lors de la création, vous choisissez ce que la clé peut faire. Ne donnez pas à une clé plus d'autorisations que votre intégration n'en a besoin.

  • Lecture (lezen) — GET /api/v1/me, GET /api/v1/transfers, GET /api/v1/transfers/<token>.
  • Créer (maken) — POST /api/v1/transfers.
  • E-mail (mailen) — envoyer des e-mails en votre nom avec send_transfer, send_folder_link, remind_recipients et request_signature du serveur MCP (voir 2c) ; ne peut être choisi qu'avec la vérification en deux étapes activée et ne fonctionne que tant qu'elle reste activée. L'API REST n'envoie pas d'e-mails.

Une nouvelle clé expire : par défaut après 90 jours, au plus tard après 365. Vous confirmez sa création avec votre mot de passe (ou un lien par e-mail) et, si votre vérification en deux étapes est activée, avec le code de votre application ; vous recevez ensuite un e-mail. Les clés que vous avez créées auparavant n'ont pas de date d'expiration et gardent lecture et création ; votre page de compte vous en avertit.

Ce que votre clé peut faire et jusqu'à quand figure dans la réponse de /api/v1/me (champ key).

2. Endpoints

URL de base : https://downloadlink.nl/api/v1. Toutes les réponses sont en JSON et limitées à votre propre compte.

La description complète est disponible en OpenAPI 3.1 sur /api/v1/openapi.json.

GET /api/v1/me

Compte + utilisation du stockage.

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 },
  "key": { "scopes": ["lezen", "maken"], "expires_at": "2027-01-11T09:12:00+00:00", "type": "api" }
}

GET /api/v1/transfers

Vos transferts (les plus récents d'abord). Paramètre ?limit= (1–200, 50 par défaut).

{
  "count": 1,
  "transfers": [
    {
      "token": "a1b2c3d4e5f6a7b8",
      "title": "Devis T3",
      "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>

Un seul transfert : métadonnées, fichiers et activité de téléchargement récente (qui/quand/quel fichier).

{
  "token": "a1b2c3d4e5f6a7b8",
  "title": "Devis T3",
  "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": "devis.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": "(paquet complet / zip)",
      "ip": "203.0.113.7"
    },
    {
      "downloaded_at": "2026-06-17T09:58:00+00:00",
      "type": "file",
      "file": "devis.pdf",
      "ip": "198.51.100.24"
    }
  ]
}

Attention : ip est l'adresse IP complète de la personne qui a téléchargé — une donnée à caractère personnel de votre destinataire, et non un chiffre anonymisé. Vous la recevez intégralement, tout comme dans l'aperçu d'activité, le CSV des téléchargements et la preuve de livraison (PDF) ; elle y figure pour pouvoir démontrer qu'un envoi a été récupéré. Si vous la traitez ou la conservez dans votre propre système, intégrez-la alors dans votre propre déclaration de confidentialité. Nous renvoyons les 100 enregistrements les plus récents ; downloads compte ces lignes. Nous les conservons au maximum 12 mois — passé ce délai, elles ne peuvent plus être récupérées, même via l'API. downloads_used est le compteur de la limite de téléchargements et reste à 0 tant que max_downloads est vide.

Limite de débit : 120 requêtes par minute et par clé (HTTP 429 en cas de dépassement).

Codes d'erreur

  • 401 unauthorized — clé absente, inconnue ou révoquée.
  • 401 key_expired — la clé a expiré (champ expired_at) ; créez-en une nouvelle sur votre page de compte.
  • 402 payment_required — votre compte n'a plus de forfait payant actif ; vos clés sont conservées.
  • 403 insufficient_scope — la clé n'a pas l'autorisation (champ required_scope).
  • 429 rate_limited — trop de requêtes, ou plus de 50 nouveaux transferts par heure (par clé et pour toutes les clés d'un compte ensemble) ; attendez le nombre de secondes indiqué dans Retry-After.

2b. Créer un transfert (écriture)

Livrez un fichier via votre propre page de téléchargement personnalisée, directement depuis votre système — un rapport ou une facture générés, par exemple :

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
}

Cas d'erreur : 402 payment_required (l'API d'écriture fait partie des formules payantes), 402 quota_exceeded (stockage plein), 413 (fichier dépassant la limite de l'API — utilisez la page d'envoi pour cela). L'habillage de la page de téléchargement suit le compte auquel appartient la clé.

2c. Serveur MCP

Pas développeur ? Connectez votre assistant IA en quelques clics : Connecter un assistant IA, étape par étape.

Pour un client MCP (Model Context Protocol, transport streamable HTTP, sans session). Utilisez la même clé dans l'en-tête Authorization ; une clé dans l'URL est refusée.

POST https://downloadlink.nl/mcp
Authorization: Bearer dlk_live_xxx
  • lezen — whoami, list_transfers, get_transfer, list_received, get_received, search_tools, find_music, find_sfx, find_templates, how_to, suggest_improvement, get_transfer_activity, get_delivery_proof, list_contacts, list_send_groups, get_branding, export_account, list_signature_requests, list_folders, get_folder, get_folder_feedback, get_changes_since, read_planning, list_rules.
  • maken — create_transfer_from_text, start_upload, complete_upload, create_request_link, extend_transfer, revoke_transfer, update_transfer, restore_transfer, delete_transfer, close_request_link, set_request_link_name, delete_received, save_contact, delete_contact, save_send_group, delete_send_group, set_branding, set_logo, set_tool_style, set_expiry_reminders, cancel_signature_request, create_folder, create_folder_dir, upload_to_folder, delete_folder_item, set_transfer_options, set_folder_options, organize_folder, save_contacts, set_defaults, save_request_template, delete_request_template, describe_tool, run_tool, edit_document, tab_job, open_file, set_rule.
  • mailen — send_transfer, send_folder_link, request_signature, remind_recipients.

Un e-mail n’est envoyé qu’avec send_transfer, send_folder_link, remind_recipients et request_signature : il faut une clé avec le droit mailen, et ce droit ne vaut que tant que la vérification en deux étapes du compte est active. Un outil pour lequel la clé n’a pas le droit n’apparaît pas dans tools/list et renvoie l’erreur d’outil insufficient_scope.

Adresse, droits et outils en JSON : /developers/mcp.json.

whoami et /api/v1/me indiquent dans plan_info ce que comprend l'offre du compte ; un refus lié à l'offre contient needed et pricing_url.

Via le serveur MCP, un nouveau transfert est valable 30 jours par défaut et 90 au maximum, y compris après prolongation ; un transfert qui n'expire jamais n'y est pas possible (expiry_not_allowed). Cela vaut pour chaque clé ; l'API REST ci-dessus garde ses propres règles.

search_tools recherche parmi tous les outils du site avec la même recherche que /tools et renvoie pour chaque outil son nom, un court résumé, la catégorie, les formats et le lien vers la page de l'outil (en néerlandais, anglais ou français). Les outils eux-mêmes fonctionnent dans le navigateur de l'utilisateur : les fichiers restent sur son ordinateur, et le serveur MCP ne traite aucun fichier.

Aucun outil du serveur MCP ne demande le mot de passe des envois du compte, comme l'API REST : la clé avec le droit maken est l'autorisation et peut donc aussi modifier, révoquer et supprimer des transferts (comme update_transfer, revoke_transfer et delete_transfer) et remplir des dossiers. Ne donnez à une clé que lezen si cela ne doit pas être possible.

get_received donne, pour chaque fichier reçu par un lien de demande du compte, un lien de téléchargement valable une heure ; un tel lien compte comme un téléchargement par le titulaire du compte, une fois par fichier et par heure.

Sans clé : un client MCP compatible OAuth trouve le serveur d'autorisation via l'en-tête WWW-Authenticate d'une réponse 401 et /.well-known/oauth-protected-resource/mcp. Le client se connecte et choisit les autorisations (lezen activé, maken désactivé, mailen impossible via OAuth). PKCE avec S256 et le paramètre resource (https://downloadlink.nl/mcp) sont obligatoires ; l'enregistrement se fait avec un Client ID Metadata Document ou via /oauth/register.

Un jeton d'accès est valable une heure et uniquement pour /mcp ; un jeton d'actualisation 30 jours et ne fonctionne qu'une fois (rotation). Le client révoque une connexion sur sa page de compte, sous Assistants connectés.

3. Webhooks

Enregistrez une https-URL sur votre page de compte (le bouton « Test » envoie immédiatement un ping-event pour vérifier votre intégration). Dès que quelqu'un télécharge votre transfert, nous envoyons un POST avec cet événement :

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": "Devis T3",
    "url": "https://downloadlink.nl/p/a1b2c3d4e5f6a7b8",
    "download_type": "zip",
    "downloaded_at": "2026-06-17T10:30:00+00:00"
  }
}

Vérifier la signature

Calculez le HMAC-SHA256 sur le corps brut de la requête avec votre secret de webhook et comparez-le en temps constant avec l'en-tête. Ignorez les messages qui ne correspondent pas.

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

Répondez avec un code HTTP 2xx pour confirmer la livraison. Après 15 tentatives échouées, nous désactivons le webhook ; un test réussi (bouton sur votre page de compte) le réactive. Seules les URL https publiques sont autorisées.