API d'iscrizione, guida per lo sviluppatore
Iscrivere una persona a un corso dopo una vendita fuori da Aladia (CRM, il tuo Stripe, un gestionale): POST /v2/integrations/enrollments con la chiave API dell'accademia, idempotenza, errori, esempi curl, Node.js e Python, il webhook enrollment.created e le iscrizioni dall'SSO.
07/10/2026
Quando un corso si vende fuori da Aladia (il CRM chiude la trattativa, il pagamento passa dal tuo Stripe o da un bonifico), l'accesso al corso lo dai con una chiamata: Aladia crea l'account (o ritrova quello esistente), iscrive la persona al corso e all'edizione e le manda l'email Sei iscritto. Il flusso completo per chi amministra l'accademia è in Come vendi un corso.
L'iscrizione è un pagamento esterno: nessun abbonamento, rata o transazione su Aladia, nessun incasso Aladia nei report. Lo staff può togliere la persona dal corso come qualsiasi iscritto (i rimborsi li gestisci tu).
Autenticazione
Una chiave API dell'accademia: Impostazioni › Sviluppatori › Chiavi API, nel contesto dell'accademia (chiavi API e webhook). Va nell'intestazione apikey di ogni richiesta, solo dal tuo server (mai nel browser).
- La chiave lavora nel workspace in cui è stata creata: si iscrive solo ai corsi di quell'accademia; un corso di un'altra accademia risponde
404. - La chiave ha i permessi di chi l'ha creata: serve Richieste: gestire (
leads.update), che hanno Proprietario e Admin.
La chiamata
POST https://api.aladia.io/v2/integrations/enrollments
apikey: <la chiave dell'accademia>
Content-Type: application/json| Campo | Obbligatorio | Descrizione |
|---|---|---|
email | sì | l'email della persona: chiave dell'account e dell'idempotenza |
courseId | sì | l'id del corso (è nell'URL /courses/<id>); il corso deve essere pubblicato |
cycleId | per i live con più edizioni | l'edizione; con una sola edizione si può omettere |
name | no | nome e cognome in un campo (oppure firstName e lastName) |
externalId | no | l'id del cliente nel tuo CRM (lettere, cifre e . _ : @ -, max 120): torna nella risposta e nel webhook. Accettato anche external_id |
language | no | it o en: la lingua dell'email e dell'account nuovo |
notify | no | false = niente email Sei iscritto (la mandi tu). Predefinito true |
Risposta
201 Created la prima volta (o quando aggiunge un'edizione nuova di un corso live), 200 OK se la persona era già iscritta a quel corso e a quell'edizione:
{
"id": "6703f1c2a4b5c6d7e8f90123",
"status": "created",
"courseId": "6ab516ab857fed8289e3f276",
"cycleId": "6ab516ab857fed8289e3f27a",
"profileId": "6703f1c2a4b5c6d7e8f90001",
"email": "mario.rossi@example.com",
"accountCreated": true,
"payment": "external",
"externalId": "hubspot-deal-4242"
}status: created (iscrizione nuova, o invito in sospeso diventato iscrizione), cycle-added (già iscritta, aggiunta l'edizione), existing (nulla da fare). accountCreated: true = l'account è nato ora: l'email contiene Imposta la password.
Idempotenza
La chiave è email + corso + edizione. Richiamare l'API con gli stessi dati non crea doppioni, non manda una seconda email e non fa partire un secondo webhook: puoi ritentare senza timori dopo un timeout. Due chiamate contemporanee per la stessa email e lo stesso corso passano una alla volta.
Errori
| Codice | errorCode | Quando |
|---|---|---|
400 | enrollment-invalid | email non valida, externalId con caratteri non ammessi, edizione che non è del corso, cycleId mancante su un live con più edizioni (il campo è in details) |
401 | chiave mancante, scaduta o eliminata | |
403 | la chiave non ha Richieste: gestire | |
403 | workspace-sso-required | accesso dal prodotto in Solo dal prodotto e la persona non ha ancora un account (vedi sotto) |
404 | il corso non esiste o non è dell'accademia della chiave | |
409 | lead-course-not-available | il corso non è pubblicato |
409 | enrollment-account-blocked | l'account con quell'email è bloccato |
Esempi
curl
curl -X POST https://api.aladia.io/v2/integrations/enrollments \
-H "apikey: $ALADIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "mario.rossi@example.com",
"name": "Mario Rossi",
"courseId": "6ab516ab857fed8289e3f276",
"cycleId": "6ab516ab857fed8289e3f27a",
"externalId": "hubspot-deal-4242"
}'Node.js (18+)
async function enroll({ email, name, courseId, cycleId, dealId }) {
const response = await fetch('https://api.aladia.io/v2/integrations/enrollments', {
method: 'POST',
headers: { apikey: process.env.ALADIA_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ email, name, courseId, cycleId, externalId: dealId }),
})
const body = await response.json()
if (!response.ok) throw new Error(`Aladia ${response.status}: ${body.errorCode ?? ''} ${body.message ?? ''}`)
/* 201 = iscritta ora, 200 = era già iscritta: in entrambi i casi è fatta. */
return body
}Python (requests)
import os
import requests
def enroll(email, name, course_id, cycle_id=None, deal_id=None):
response = requests.post(
"https://api.aladia.io/v2/integrations/enrollments",
headers={"apikey": os.environ["ALADIA_API_KEY"]},
json={"email": email, "name": name, "courseId": course_id, "cycleId": cycle_id, "externalId": deal_id},
timeout=30,
)
if response.status_code not in (200, 201):
raise RuntimeError(f"Aladia {response.status_code}: {response.text}")
return response.json()Con Make o Zapier: un modulo HTTP › Make a request con gli stessi metodo, intestazioni e corpo, dopo il passo "pagamento ricevuto" o "trattativa vinta".
Webhook
Nella stessa accademia, Impostazioni › Webhook:
lead.created: una richiesta di informazioni dal sito (il punto di partenza della vendita dal CRM);lead.updated: la richiesta cambia stato o assegnatario (anche quando Iscrivi la porta a Iscritta);enrollment.created: un'iscrizione nuova (o un'edizione aggiunta) dall'API o da Iscrivi. Non parte quando la risposta èexisting.
Ogni consegna è un POST JSON all'URL del webhook, con questo corpo:
{
"event": "enrollment",
"data": {
"event": "enrollment.created",
"enrollment": {
"id": "6703f1c2a4b5c6d7e8f90123",
"status": "created",
"course": { "id": "6ab516ab857fed8289e3f276", "title": "Master in Diritto" },
"cycleId": "6ab516ab857fed8289e3f27a",
"profileId": "6703f1c2a4b5c6d7e8f90001",
"email": "mario.rossi@example.com",
"name": "Mario Rossi",
"externalId": "hubspot-deal-4242",
"payment": "external",
"via": "api",
"accountCreated": true,
"createdAt": "2026-10-07T09:30:00.000Z"
}
}
}via: api o lead (Iscrivi nelle Richieste).
Iscrizioni dall'SSO
Se l'accademia usa l'accesso dal tuo prodotto, anche il claim courses del JWT iscrive: a ogni accesso l'utente entra nei corsi indicati. Sono iscrizioni senza acquisto Aladia come quelle dell'API, segnate però dal prodotto (SSO) e non come pagamento esterno: le gestisce il prodotto (replace_courses le può togliere), mentre quelle dell'API restano finché lo staff non le toglie. Non serve un claim per dire "pagato": su Aladia nessuna delle due conta come incasso.
Quale usare:
| Situazione | Strada |
|---|---|
| Il prodotto sa a ogni login a quali corsi ha diritto l'utente | claim courses (e replace_courses) |
| La vendita la chiude un CRM o un checkout esterno, una volta | API d'iscrizione |
| Accademia in Solo dal prodotto e la persona non è mai entrata | claim courses: l'API risponde 403 workspace-sso-required perché non crea account fuori dal prodotto |
In Solo dal prodotto l'API iscrive chi ha già l'account (è entrato almeno una volta dal prodotto). In Misto o con l'SSO spento crea l'account come sempre.
SSO dei clienti, guida per lo sviluppatore
Come il tuo prodotto fa entrare i suoi utenti nell'accademia Aladia con lo stesso account, firmando un JWT. Flusso, claim, esempi Node.js, Python e PHP (HS256 e RS256/JWKS), deep link, remote login, logout, iscrizioni ai corsi, errori e checklist di sicurezza.
Profilo, post e community
Il tuo profilo pubblico, il feed, le domande e le storie.