FastDesk ← Torna al sito

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.

Base URL: https://fastdesk.it · Formato: JSON · HTTPS: obbligatorio

Panoramica

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:

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 AccountLink accorciati🔑 API per integrazioneCrea 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.

⚠ Sicurezza: non usare mai la API key da JavaScript browser-side: chiunque visiti la pagina la vedrebbe. Usala solo da codice server (PHP/Node/Python/Go) dove resta nascosta.

Limiti & sicurezza

LimiteValoreCosa succede al raggiungimento
Creazioni link per API key10 / oraHTTP 429 con header Retry-After
Creazioni link per IP10 / minutoHTTP 429
API key attive per account10Errore creazione 11ª chiave
Link totali per account10 (ring buffer)Il link più vecchio viene cancellato per fare posto al nuovo
Lunghezza URL target2000 caratteriHTTP 400
Lunghezza password1-100 caratteriHTTP 400
Max downloads1-1000HTTP 400
Validità (giorni)1-3650HTTP 400
Tentativi password sul link5Link bloccato 1 ora (anti-bruteforce)

L'URL target non può puntare a:

Codici di errore

200OK — la risposta contiene il payload richiesto 400Bad Request — parametri mancanti o non validi (vedi 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-KeyrichiestoLa tua API key fdk_live_...
Content-Typerichiestoapplication/json

Body (JSON)

CampoTipoDescrizione
urlstringrichiestoURL di destinazione, deve iniziare con http:// o https://, max 2000 caratteri.
passwordstringopzionaleSe presente, il visitatore dovrà inserirla per accedere. 1-100 caratteri. Hashata con bcrypt (cost 10) sul server.
maxDownloadsintegeropzionaleNumero massimo di download. 1-1000. Decremento atomico: due click in parallelo non possono entrambi superare il limite.
expiresInDaysintegeropzionaleGiorni 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
    }
  ]
}
Differenza 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

  1. Apertura di https://fastdesk.it/s/ab3f7kzm
  2. Se il link richiede password → form di inserimento (vedi sezione successiva)
  3. Se il link è scaduto / esaurito / bloccato → pagina di errore (HTTP 410/423)
  4. Altrimenti → landing page brandizzata FastDesk con countdown 5 secondi
  5. Click "Scarica ora" o fine countdown → GET /s/ab3f7kzm/go
  6. Server: download_count++ (atomico, se maxDownloads è 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": "...":

  1. Il visitatore apre /s/CODE e vede un form "🔒 Link protetto da password"
  2. Inserisce la password e fa POST a /s/CODE/unlock
  3. Server confronta con bcrypt:
    • ✓ Corretta → cookie JWT fd_su_CODE valido 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
  4. 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).

StatoHTTPCosa vede l'utenteCosa fa il server
Attivo200Landing 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

Changelog

VersioneDataNote
5.0.432026-04-26API keys server-to-server (X-API-Key + Authorization Bearer), rate limit 10/h per chiave, gestione chiavi nell'area Account.
5.0.412026-04-26Protezione password (bcrypt), maxDownloads con decremento atomico, expiresInDays, auto-lock dopo 5 password sbagliate.
5.0.202026-03-15Sistema short links iniziale: codici 8 char, ring buffer 10/utente, statistiche click, ban anti-flood.

Domande, bug, feature request: support@fastdesk.it