Un'API REST progettata con cura è un piacere da integrare. Al contrario, un'architettura confusa genera ticket di supporto infiniti, bug lato client e frustrazione negli sviluppatori. La chiave per il successo risiede nell'adozione di standard coerenti e collaudati che rendano il tuo endpoint intuitivo, prevedibile e facile da scalare. In questo articolo, esploriamo i principi seguiti dai giganti del settore come Stripe, GitHub e Twilio.

1. Usa i sostantivi per le risorse, non i verbi

L'architettura REST è focalizzata sulle risorse. Le tue URL devono descrivere gli oggetti (sostantivi), non le azioni (verbi). È il metodo HTTP (GET, POST, PUT, DELETE) a definire il tipo di operazione da eseguire:

Sostantivi vs Verbi nelle URL
# ❌ URL basate su verbi (stile RPC)
GET  /getUser?id=42
POST /createUser
POST /deleteUser?id=42
POST /updateUserEmail

# ✅ URL basate su sostantivi (stile REST)
GET    /users/42          # Recupera utente 42
POST   /users             # Crea un nuovo utente
DELETE /users/42          # Elimina utente 42
PATCH  /users/42          # Aggiorna campi specifici dell'utente 42

2. Utilizza i plurali per le collezioni

Per mantenere la coerenza, utilizza sempre sostantivi al plurale per le collezioni. Questa convenzione rende la lettura dell'API estremamente naturale: /users identifica l'intero insieme di utenti, mentre /users/42 punta alla singola entità:

Endpoint di Collezione e Risorsa
GET    /articles          # Elenco articoli
POST   /articles          # Crea un articolo
GET    /articles/slug     # Ottieni un articolo specifico
PUT    /articles/slug     # Sostituisci un intero articolo
PATCH  /articles/slug     # Aggiorna parzialmente un articolo
DELETE /articles/slug     # Elimina un articolo

3. Utilizza correttamente i metodi HTTP

Assicurati di assegnare il metodo corretto a ogni azione per mantenere la semantica intatta:

  • GET — Recupero dati. Deve essere "safe" (nessun effetto collaterale) e idempotente.
  • POST — Creazione di nuove risorse. Non idempotente (chiamate multiple creano duplicati).
  • PUT — Sostituzione completa di una risorsa esistente. Idempotente.
  • PATCH — Aggiornamento parziale di una risorsa. Non richiede idempotenza.
  • DELETE — Rimozione di una risorsa. Idempotente (cancellare una risorsa già rimossa dovrebbe restituire 404).

4. Sfrutta i codici di stato HTTP standard

I codici di stato servono a informare il client sull'esito dell'operazione senza costringerlo a parsare il corpo della risposta alla ricerca di errori:

Codici di stato essenziali
200 OK              # Successo (GET, PATCH, DELETE)
201 Created         # Successo (POST)
204 No Content      # Successo (DELETE, nessuna risposta)
400 Bad Request     # Sintassi errata o validazione fallita
401 Unauthorized    # Credenziali mancanti o errate
403 Forbidden       # Autenticato ma senza permessi sulla risorsa
404 Not Found       # Risorsa inesistente
409 Conflict        # Conflitto di stato (es. email duplicata)
422 Unprocessable   # Sintassi valida, ma dati logicamente errati
429 Too Many Requests  # Limite di richieste superato
500 Internal Server Error  # Errore lato server imprevisto

Non nascondere mai errori in una risposta 200 OK. Usa sempre i codici 4xx o 5xx per comunicare chiaramente che qualcosa è andato storto.

5. Struttura degli errori prevedibile

Adotta una struttura uniforme per le risposte di errore, facilitando la gestione delle eccezioni da parte dei client:

Formato coerente per gli errori
{
  "error": {
    "status": 422,
    "code": "VALIDATION_ERROR",
    "message": "Dati della richiesta non validi.",
    "details": [
      {
        "field": "email",
        "message": "Formato email non corretto."
      },
      {
        "field": "password",
        "message": "La password deve avere almeno 8 caratteri."
      }
    ]
  }
}

6. Versionamento sin dal primo giorno

Le API cambiano costantemente. Senza un versionamento, qualsiasi modifica strutturale interromperà le integrazioni esistenti. Strategie consigliate:

  • URL versioning (consigliato): /api/v1/users, /api/v2/users — Semplice, esplicito e facile da testare.
  • Header versioning: Accept: application/vnd.myapi.v2+json — Pulito, ma meno intuitivo da testare via browser.
  • Query parameter: /api/users?version=2 — Molto semplice, ma meno standard.

Consigliamo il versionamento nelle URL per la sua chiarezza immediata. Incrementa la versione (v1 → v2) solo per modifiche "breaking".

7. Implementa sempre la paginazione

Non restituire mai liste infinite. Pagina sempre le tue collezioni e includi i metadati di navigazione:

Paginazione basata su cursore
{
  "data": [
    { "id": "usr_abc123", "name": "Alice" },
    { "id": "usr_def456", "name": "Bob" }
  ],
  "pagination": {
    "total": 847,
    "page": 1,
    "per_page": 20,
    "next_cursor": "usr_def456",
    "has_more": true
  }
}

La paginazione basata su cursore (usando l'ID dell'ultimo elemento) è preferibile rispetto a quella basata su offset (LIMIT/OFFSET), garantendo coerenza anche se vengono aggiunti o rimossi record tra una richiesta e l'altra.

8. HTTPS: Non è opzionale

Ogni API moderna deve essere servita esclusivamente via HTTPS. Non ci sono compromessi: trasmettere token, password o dati sensibili in chiaro è un rischio di sicurezza che nessun professionista dovrebbe correre.

9. Rate Limiting

Proteggi i tuoi endpoint dagli abusi e garantisci un utilizzo equo. Comunica sempre lo stato corrente del limite tramite i header standard:

Header di Rate Limiting
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 734
X-RateLimit-Reset: 1718481600

Se il limite viene superato, rispondi con 429 Too Many Requests includendo un header Retry-After.

10. Documentazione accurata

Un'API senza documentazione è un'API fantasma. Utilizza le specifiche OpenAPI (ex Swagger) per documentare i tuoi endpoint; questo standard permette di generare automaticamente documentazione interattiva, SDK per client e suite di test.

Lavora con i dati JSON istantaneamente

Formatta le risposte API per il debug o comprimi i payload JSON per la produzione con i nostri strumenti gratuiti.