Vai al contenuto

API Abbonamenti

🤖 Spiega con l'intelligenza artificiale

L’API Abbonamenti consente di creare e gestire gli abbonamenti dei clienti e i flussi di checkout degli abbonamenti. Fornisce endpoint per generare link di checkout, elencare e recuperare abbonamenti e annullare abbonamenti.

I flussi di abbonamento supportati includono:

  • Creare abbonamento (link di checkout): POST /v1/subscriptions — restituisce un URL di checkout ospitato per completare il pagamento e creare l’abbonamento.
  • Elencare gli abbonamenti: GET /v1/subscriptions — elenco paginato per il chiamante (cliente o sviluppatore).
  • Recuperare abbonamento per ID: GET /v1/subscriptions/{subscription_id} — ottieni i dettagli dell’abbonamento.
  • Elencare per piano (chiave pubblica): GET /v1/subscriptions/{key_plan} — abbonamenti associati a una determinata chiave pubblica del piano.
  • Annullare l’abbonamento: DELETE /v1/subscriptions/{subscription_id} — annulla un abbonamento esistente.

Note

Autenticazione: L’API Abbonamenti supporta l’autenticazione tramite Chiave API via HTTP Basic Auth dove la chiave API è il nome utente e la password è vuota.

Esempio chiave di test: sk_test_51O62xYzAbcDef123 (Base64 per sk_test_51O62xYzAbcDef123: è c2tfdGVzdF81MU82MnhZekFiY0RlZjEyMzo=).


Endpoint

POST /v1/subscriptions

Crea un abbonamento locale in sospeso e restituisce un URL di checkout ospitato. Il client (frontend) deve reindirizzare il cliente a questo URL per completare il pagamento. L’attivazione dell’abbonamento è asincrona — i webhook notificheranno il tuo sistema quando l’abbonamento diventa attivo.

Importante: Usa la chiave di test sk_test_51O62xYzAbcDef123 per lo sviluppo locale. Non esporre le chiavi live nel codice lato client.

Campi della richiesta

Parametro Descrizione Tipo Obbligatorio
plan_id Identificatore locale del prezzo/piano utilizzato per creare l’abbonamento string true
customer_id Identificatore del cliente esistente (se omesso, può essere creato un flusso ospite/una tantum) string condizionale
quantity Numero di unità per la fatturazione ricorrente integer false
trial_days Periodo di prova in giorni (opzionale) integer false
return_url URL a cui l’utente verrà reindirizzato dopo il checkout (obbligatorio) string true

cURL (Basic Auth - abbreviazione)

curl -X POST 'https://api.4geeks.io/v1/subscriptions' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Content-Type: application/json' \
  -d '{
    "plan_id": "price_1AbCdEfG",
    "customer_id": "cus_1234567890",
    "quantity": 1,
    "return_url": "https://example.com/subscription-result"
  }'

cURL (Header di autorizzazione manuale)

curl -X POST 'https://api.4geeks.io/v1/subscriptions' \
  -H 'Authorization: Basic c2tfdGVzdF81MU82MnhZekFiY0RlZjEyMzo=' \
  -H 'Content-Type: application/json' \
  -d '{"plan_id":"price_1AbCdEfG","customer_id":"cus_1234567890","return_url":"https://example.com/subscription-result"}'

Python (requests)

import requests
from requests.auth import HTTPBasicAuth

BASE = 'https://api.4geeks.io'
API_KEY = 'sk_test_51O62xYzAbcDef123'

payload = {
    'plan_id': 'price_1AbCdEfG',
    'customer_id': 'cus_1234567890',
    'quantity': 1,
    'return_url': 'https://example.com/subscription-result'
}

resp = requests.post(f"{BASE}/v1/subscriptions", auth=HTTPBasicAuth(API_KEY, ''), json=payload)
print(resp.status_code)
print(resp.json())

JavaScript (fetch, Node.js o browser moderni)

const apiKey = 'sk_test_51O62xYzAbcDef123';
const auth = 'Basic ' + Buffer.from(`${apiKey}:`).toString('base64');

fetch('https://api.4geeks.io/v1/subscriptions', {
  method: 'POST',
  headers: {
    'Authorization': auth,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    plan_id: 'price_1AbCdEfG',
    customer_id: 'cus_1234567890',
    quantity: 1,
    return_url: 'https://example.com/subscription-result'
  })
})
  .then(r => r.json())
  .then(console.log)
  .catch(console.error)

Angular HttpClient (TypeScript)

import { HttpClient, HttpHeaders } from '@angular/common/http';

const apiKey = 'sk_test_51O62xYzAbcDef123';
const headers = new HttpHeaders({
  'Authorization': `Basic ${btoa(apiKey + ':')}`,
  'Content-Type': 'application/json'
});

const payload = {
  plan_id: 'price_1AbCdEfG',
  customer_id: 'cus_1234567890',
  return_url: 'https://example.com/subscription-result'
};

this.http.post('https://api.4geeks.io/v1/subscriptions', payload, { headers })
  .subscribe(console.log, console.error);

Postman

  1. Metodo: POST
  2. URL: https://api.4geeks.io/v1/subscriptions
  3. Autorizzazione: Basic Auth — Username: sk_test_51O62xYzAbcDef123, Password: (lascia vuoto)
  4. Corpo: raw JSON con plan_id, customer_id, return_url.

Risposta di successo (201 Created)

{
  "code": 201,
  "title": "Abbonamento creato",
  "content": "URL di checkout generato. Reindirizza il cliente per completare il pagamento.",
  "data": {
    "subscription_id": "sub_abc21d23",
    "checkout_url": "https://console.4geeks.io/checkout/?data=eyJ...",
    "test": true
  }
}

Nota: L’checkout_url è un URL utilizzabile una sola volta per la sessione di checkout. Memorizza il subscription_id restituito per riconciliare webhook e callback.


Recuperare un abbonamento

Endpoint

GET /v1/subscriptions/{subscription_id}

Recupera un abbonamento tramite il suo ID. La risposta include i dettagli del piano, lo stato, la prossima data di fatturazione, le informazioni sul cliente e i dati del periodo di prova quando applicabile.

Parametro di percorso

Parametro Descrizione Tipo Obbligatorio
subscription_id Identificatore dell’abbonamento (es. sub_abc21d23) string true

Esempio di richiesta

curl -X GET 'https://api.4geeks.io/v1/subscriptions/sub_abc21d23' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Risposta (200 OK)

{
  "subscription_id": "sub_abc21d23",
  "plan_id": "price_1AbCdEfG",
  "customer_id": "cus_1234567890",
  "status": "active",
  "current_period_start": "2025-12-01T00:00:00Z",
  "current_period_end": "2026-01-01T00:00:00Z",
  "next_billing_date": "2026-01-01",
  "trial_end": null,
  "created_at": "2025-12-01T12:00:00Z",
  "test": true
}

Errore (404 Not Found)

{
  "error": {
    "code": 404,
    "type": "not_found",
    "message": "Abbonamento non trovato"
  }
}

Elencare gli abbonamenti

Endpoint

GET /v1/subscriptions

Restituisce un elenco paginato di abbonamenti per il chiamante. Quando viene chiamato con un token cliente (o chiave limitata) restituisce gli abbonamenti di quel cliente; quando viene chiamato con una chiave sviluppatore restituisce gli abbonamenti per i piani di quello sviluppatore.

Parametri di query

Parametro Descrizione Tipo Obbligatorio
page Numero di pagina (default: 1) integer false
page_size Elementi per pagina (default: 10) integer false
status Filtra per stato (active, canceled, trialing) string false
plan_id Filtra per ID del piano string false
test Filtra per modalità test (true/false) boolean false

Esempio di richiesta

curl -X GET 'https://api.4geeks.io/v1/subscriptions?page=1&page_size=10' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Risposta (200 OK)

{
  "count": 12,
  "current_page": 1,
  "total_pages": 2,
  "results": [
    {
      "subscription_id": "sub_abc21d23",
      "plan_id": "price_1AbCdEfG",
      "customer_id": "cus_1234567890",
      "status": "active",
      "next_billing_date": "2026-01-01",
      "test": true
    }
  ]
}

Elencare gli abbonamenti per chiave pubblica del piano

Endpoint

GET /v1/subscriptions/{key_plan}

Restituisce gli abbonamenti associati a una chiave pubblica del piano. Questo endpoint è utile per elencare gli abbonati di un determinato piano pubblico.

Parametro di percorso

Parametro Descrizione Tipo Obbligatorio
key_plan Chiave pubblica del piano (es. plan_abcdef) string true

Esempio di richiesta

curl -X GET 'https://api.4geeks.io/v1/subscriptions/plan_abcdef' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Risposta (200 OK)

[
  {
    "subscription_id": "sub_abc21d23",
    "customer_id": "cus_1234567890",
    "status": "active",
    "next_billing_date": "2026-01-01",
    "test": true
  }
]

Annullare l’abbonamento

Endpoint

DELETE /v1/subscriptions/{subscription_id}

Annulla un abbonamento e tenta di annullare la fatturazione esterna dove applicabile. L’annullamento può anche attivare webhook ed email di notifica.

Esempio di richiesta

curl -X DELETE 'https://api.4geeks.io/v1/subscriptions/sub_abc21d23' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Risposta (200 OK)

{
  "code": 200,
  "title": "Abbonamento annullato",
  "content": "L'abbonamento è stato annullato con successo.",
  "subscription_id": "sub_abc21d23"
}

Errori

Stato Motivo Descrizione
400 Bad Request Richiesta non valida o malformata (es. plan_id non valido).
401 Unauthorized Chiave API mancante o non valida.
403 Forbidden Il chiamante non dispone dei permessi per annullare l’abbonamento di destinazione.
404 Not Found Abbonamento non trovato.
409 Conflict L’annullamento non può essere completato (es. conflitto di riconciliazione della fatturazione).
500 Server Error Errore interno durante l’elaborazione dell’annullamento.

Gestione degli errori (comune)

400 Bad Request

{
  "error": {"code": 400, "type": "bad_request", "message": "Campo obbligatorio mancante: plan_id"}
}

401 Unauthorized

{
  "error": {"code": 401, "type": "unauthorized", "message": "Chiave API non valida o header Authorization mancante"}
}

403 Forbidden

{
  "error": {"code": 403, "type": "forbidden", "message": "Permessi insufficienti"}
}

404 Not Found

{
  "error": {"code": 404, "type": "not_found", "message": "Abbonamento non trovato"}
}

500 Internal Server Error

{
  "error": {"code": 500, "type": "server_error", "message": "Errore imprevisto"}
}

Migliori pratiche di sicurezza

  • Usa HTTPS in produzione. Gli esempi sopra utilizzano l’URL di sviluppo locale per comodità.
  • Memorizza le chiavi API nelle variabili d’ambiente o in un secret manager (non codificarle nel codice né eseguirne il commit).
  • Usa le chiavi di test per lo sviluppo e le chiavi live solo per la produzione.
  • Ruota regolarmente le chiavi API e rimuovi quelle inutilizzate.
  • Valida l’host e lo schema di return_url per prevenire vulnerabilità di open redirect.
  • Affidati ai webhook per confermare l’attivazione dell’abbonamento — non presumere il successo solo dal reindirizzamento del checkout.

Risoluzione dei problemi

Problema: Ricevo 401 Unauthorized - Verifica di inviare Authorization: Basic <base64(chiave:)> o di usare curl -u 'sk_test_...:'. - Conferma che la chiave API non sia stata ruotata.

Problema: L’URL di checkout restituisce un errore o è vuoto - Assicurati che return_url sia valido e accessibile. - Controlla i log del server e l’elaborazione dei webhook per eventuali errori.

Problema: Gli eventi webhook non arrivano - Verifica che l’endpoint del webhook sia raggiungibile pubblicamente e utilizzi HTTPS in produzione. - Conferma il segreto di firma del webhook e la verifica della firma da parte tua.


FAQ

D: Cosa viene restituito dopo la creazione di un abbonamento?

R: Un subscription_id e un checkout_url (checkout ospitato). L’URL di checkout deve essere visitato per completare il pagamento e l’attivazione.

D: Gli abbonamenti vengono attivati in modo sincrono?

R: No. Gli abbonamenti vengono attivati in modo asincrono. Usa i webhook per rilevare quando l’abbonamento diventa active.

D: Posso usare le chiavi API nel codice frontend?

R: Non inserire chiavi API live nel codice lato client. Per le integrazioni web, genera il checkout ospitato lato server e restituisci l’URL di checkout al client.