FastDesk API
REST API per integrare il sistema di link accorciati di FastDesk nel tuo sito o script. Server-to-server, autenticazione via API key, supporto password / scadenza / limite download.
https://fastdesk.it · Formato: JSON · HTTPS: obbligatorioPanoramica
L'API espone le funzionalità del shortener disponibile nell'area Account: crei link brevi del tipo https://fastdesk.it/s/ab3f7kzm che reindirizzano a un URL esterno qualsiasi. Su ogni link puoi attivare:
- Password — il visitatore deve inserirla per accedere al download
- Limite download — il link funziona N volte poi si autodisabilita
- Scadenza — il link cessa di funzionare dopo N giorni
- Statistiche — IP, browser, referer, paese, timestamp di ogni accesso
Quando un visitatore apre il link viene mostrata una landing page brandizzata FastDesk con countdown di 5 secondi (5 lingue automatiche) prima del redirect 302 finale. La pagina non espone mai l'URL di destinazione nel sorgente HTML.
Autenticazione
Tutte le richieste a /api/shortlinks* richiedono autenticazione. Hai due opzioni:
1. API Key (consigliato per server-to-server)
Genera una chiave dal tuo account FastDesk: login → sezione Account → Link accorciati → 🔑 API per integrazione → Crea API key.
La chiave ha formato fdk_live_<43 caratteri> e viene mostrata una sola volta: salvala subito in un secret manager o variabile d'ambiente.
Passa la chiave in uno dei due header equivalenti:
# Header dedicato (preferito) X-API-Key: fdk_live_a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6q7R8s9T0u1V2 # Oppure Bearer (se più comodo per il tuo client HTTP) Authorization: Bearer fdk_live_a1B2c3D4...
2. Sessione web (JWT)
Se chiami l'API dal browser su fastdesk.it stesso (es. estensione, dashboard custom), la sessione cookie già esistente fa autenticazione automatica. Niente da fare.
Limiti & sicurezza
| Limite | Valore | Cosa succede al raggiungimento |
|---|---|---|
| Creazioni link per API key | 10 / ora | HTTP 429 con header Retry-After |
| Creazioni link per IP | 10 / minuto | HTTP 429 |
| API key attive per account | 10 | Errore creazione 11ª chiave |
| Link totali per account | 10 (ring buffer) | Il link più vecchio viene cancellato per fare posto al nuovo |
| Lunghezza URL target | 2000 caratteri | HTTP 400 |
| Lunghezza password | 1-100 caratteri | HTTP 400 |
| Max downloads | 1-1000 | HTTP 400 |
| Validità (giorni) | 1-3650 | HTTP 400 |
| Tentativi password sul link | 5 | Link bloccato 1 ora (anti-bruteforce) |
L'URL target non può puntare a:
- Reti private (10.*, 172.16-31.*, 192.168.*, 127.*, fc00::/7) — anti-SSRF
- Lo stesso dominio FastDesk (anti-loop)
Codici di errore
error nel body)
401Unauthorized — API key mancante, scaduta, revocata o malformata
403Forbidden — operazione non disponibile via API key (es. gestione delle key stesse)
404Not Found — risorsa inesistente o non di tua proprietà
429Too Many Requests — rate limit superato. Header Retry-After indica i secondi di attesa
500Internal Server Error — segnalalo a support@fastdesk.it
Ogni risposta di errore ha sempre forma:
{ "error": "Descrizione leggibile in italiano" }
POST/api/shortlinks
Crea un nuovo link breve. Solo il campo url è obbligatorio; tutto il resto è opzionale.
Headers
X-API-Key | richiesto | La tua API key fdk_live_... |
Content-Type | richiesto | application/json |
Body (JSON)
| Campo | Tipo | Descrizione | |
|---|---|---|---|
url | string | richiesto | URL di destinazione, deve iniziare con http:// o https://, max 2000 caratteri. |
password | string | opzionale | Se presente, il visitatore dovrà inserirla per accedere. 1-100 caratteri. Hashata con bcrypt (cost 10) sul server. |
maxDownloads | integer | opzionale | Numero massimo di download. 1-1000. Decremento atomico: due click in parallelo non possono entrambi superare il limite. |
expiresInDays | integer | opzionale | Giorni di validità a partire da ora. 1-3650. Dopo la scadenza il link risponde 410 e viene rimosso dal DB entro 24h. |
Risposta (200 OK)
{
"ok": true,
"code": "ab3f7kzm",
"url": "https://fastdesk.it/s/ab3f7kzm",
"target": "https://example.com/file.zip",
"has_password": true,
"max_downloads": 1,
"expires_at": "2026-05-03T19:34:48.000Z"
}Esempi
curl -X POST https://fastdesk.it/api/shortlinks \ -H "X-API-Key: fdk_live_LA_TUA_CHIAVE" \ -H "Content-Type: application/json" \ -d '{ "url": "https://miosito.it/files/contratto.pdf", "password": "segreto123", "maxDownloads": 1, "expiresInDays": 7 }'
<?php $ch = curl_init('https://fastdesk.it/api/shortlinks'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'X-API-Key: ' . $_ENV['FASTDESK_API_KEY'], 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'url' => 'https://miosito.it/files/contratto.pdf', 'password' => 'segreto123', 'maxDownloads' => 1, 'expiresInDays' => 7, ]), ]); $resp = json_decode(curl_exec($ch), true); if (empty($resp['ok'])) { throw new RuntimeException($resp['error'] ?? 'API error'); } echo $resp['url']; // https://fastdesk.it/s/ab3f7kzm
const res = await fetch('https://fastdesk.it/api/shortlinks', { method: 'POST', headers: { 'X-API-Key': process.env.FASTDESK_API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ url: 'https://miosito.it/files/contratto.pdf', password: 'segreto123', maxDownloads: 1, expiresInDays: 7, }), }); if (!res.ok) throw new Error('API error ' + res.status); const { url } = await res.json(); console.log(url); // https://fastdesk.it/s/ab3f7kzm
import os, requests r = requests.post( 'https://fastdesk.it/api/shortlinks', headers={ 'X-API-Key': os.environ['FASTDESK_API_KEY'], 'Content-Type': 'application/json', }, json={ 'url': 'https://miosito.it/files/contratto.pdf', 'password': 'segreto123', 'maxDownloads': 1, 'expiresInDays': 7, }, timeout=10, ) r.raise_for_status() print(r.json()['url'])
GET/api/shortlinks
Restituisce la lista dei tuoi link attivi (max 10 per account).
Risposta (200 OK)
{
"max": 10,
"links": [
{
"id": 42,
"code": "ab3f7kzm",
"target_url": "https://miosito.it/files/contratto.pdf",
"click_count": 7,
"last_click_at": "2026-04-26T20:15:32.000Z",
"created_at": "2026-04-20T09:00:00.000Z",
"max_downloads": 10,
"download_count": 3,
"expires_at": "2026-05-20T09:00:00.000Z",
"locked_until": null,
"has_password": true
}
]
}click_count vs download_count: il primo conta tutte le aperture della landing page; il secondo solo i download effettivamente consumati (post-password e pre-redirect). Il limite maxDownloads agisce su download_count.GET/api/shortlinks/:id/clicks
Statistiche dettagliate degli ultimi 200 accessi a un singolo link.
Risposta (200 OK)
{
"link": { "id": 42, "code": "ab3f7kzm", "target_url": "...", "click_count": 7 },
"clicks": [
{
"ip": "81.114.176.42",
"user_agent": "Mozilla/5.0 (Macintosh...) Chrome/120.0",
"referer": "https://miosito.it/download-page",
"clicked_at": "2026-04-26T20:15:32.000Z"
}
]
}DELETE/api/shortlinks/:id
Elimina un link. Da quel momento /s/CODE risponde 404. Anche le statistiche vengono cancellate (cascading delete su short_link_clicks).
Risposta
{ "ok": true }
Flusso lato visitatore
- Apertura di
https://fastdesk.it/s/ab3f7kzm - Se il link richiede password → form di inserimento (vedi sezione successiva)
- Se il link è scaduto / esaurito / bloccato → pagina di errore (HTTP 410/423)
- Altrimenti → landing page brandizzata FastDesk con countdown 5 secondi
- Click "Scarica ora" o fine countdown →
GET /s/ab3f7kzm/go - Server:
download_count++(atomico, semaxDownloadsè settato), redirect 302 al target
L'URL di destinazione non appare mai nel sorgente HTML della landing: il redirect 302 lo invia il server. L'header Referrer-Policy: no-referrer impedisce al browser di leakare l'origine FastDesk al sito target.
Link con password
Quando crei il link con "password": "...":
- Il visitatore apre
/s/CODEe vede un form "🔒 Link protetto da password" - Inserisce la password e fa POST a
/s/CODE/unlock - Server confronta con bcrypt:
- ✓ Corretta → cookie JWT
fd_su_CODEvalido 15 min, redirect alla landing standard - ✗ Sbagliata → counter
failed_pwd_count++ - 5° errore →
locked_until = NOW + 1h, link bloccato anche per chi ha la password giusta
- ✓ Corretta → cookie JWT
- Una volta sbloccato, le 15 minuti permettono refresh / re-download senza ridigitare la password
Scadenza & limite download
Le due protezioni si combinano (la prima che scatta vince).
| Stato | HTTP | Cosa vede l'utente | Cosa fa il server |
|---|---|---|---|
| Attivo | 200 | Landing page | — |
| Scaduto (expires_at) | 410 | "Link scaduto" | Auto-eliminato dal DB entro 24h |
| Esaurito (max_downloads) | 410 | "Numero di download esaurito" | Resta nel DB ma 410 perpetuo |
| Bloccato (5 password sbagliate) | 423 | "Bloccato fino a YYYY-MM-DD HH:MM" | Auto-sblocco dopo 1h |
Esempio: condivisione one-shot
Vuoi mandare un file al cliente e sicurezza che venga scaricato esattamente una volta:
{
"url": "https://miosito.it/files/contratto.pdf",
"maxDownloads": 1,
"expiresInDays": 3
}Risultato: il primo che apre il link scarica il file; per chiunque altro (incluso eventuale forward) il link è 410.
Esempio: file con password (condivisa per altro canale)
Mandi il link via email e la password via WhatsApp:
{
"url": "https://drive.google.com/file/d/.../view",
"password": "Pizza2026!",
"maxDownloads": 5,
"expiresInDays": 14
}Esempio: link temporaneo che scade in 24h
{
"url": "https://miosito.it/promo/sconto-flash",
"expiresInDays": 1
}Best practice di sicurezza
- Conserva la API key in un secret manager (variabile d'ambiente, AWS Secrets Manager, HashiCorp Vault). Non committarla mai in repository git.
- Una chiave per integrazione: usa l'etichetta per ricordarti dove l'hai messa (es. "Sito file.it produzione"). Se compromessa, revochi solo quella senza rompere le altre.
- Mai esporre la key client-side: niente
fetch()da JavaScript browser con la chiave hardcoded. La chiave deve restare nel tuo backend. - Monitora
last_used_atelast_used_ipnella lista chiavi: se vedi un IP che non riconosci, revoca la chiave. - Password forti sui link sensibili: bcrypt è robusto ma la velocità del test "5 tentativi/lock" non protegge da una password tipo 1234. Usa almeno 8 caratteri misti.
- HTTPS sempre: l'API rifiuta connessioni in chiaro. Il tuo client deve presentare un certificato CA standard (no self-signed se chiami da locale).
Changelog
| Versione | Data | Note |
|---|---|---|
| 5.0.43 | 2026-04-26 | API keys server-to-server (X-API-Key + Authorization Bearer), rate limit 10/h per chiave, gestione chiavi nell'area Account. |
| 5.0.41 | 2026-04-26 | Protezione password (bcrypt), maxDownloads con decremento atomico, expiresInDays, auto-lock dopo 5 password sbagliate. |
| 5.0.20 | 2026-03-15 | Sistema short links iniziale: codici 8 char, ring buffer 10/utente, statistiche click, ban anti-flood. |
Domande, bug, feature request: support@fastdesk.it
