API & Integrazioni
Collega CVforge a Claude Desktop, n8n, Cursor e alle tue automazioni tramite l'API MCP. Upload di CV, recupero delle ottimizzazioni, gestione del tuo profilo — tutto è accessibile in modo programmatico.
Endpoint
api.cvforge.co/mcp
Protocollo
MCP · JSON-RPC 2.0
Trasporto
HTTP POST
Auth
PAT o OAuth2
1. Prerequisiti
L'accesso all'API MCP è incluso nel pack Expert.
- Avere un account CVforge attivo con un abbonamento Expert in corso.
- Creare un Personal Access Token (PAT) dalla pagina Impostazioni → API & Integrazioni.
2. Autenticazione
CVforge supporta due metodi di autenticazione. Per la maggior parte delle integrazioni personali (n8n, script, Claude Desktop), usa un PAT. Per applicazioni di terze parti, usa il flusso OAuth 2.0 Authorization Code + PKCE.
2.1 Personal Access Token (PAT)
Un PAT è un token opaco con prefisso mcp_pat_. Viene mostrato una sola volta al momento della creazione — conservalo con cura.
Utilizzo in ogni richiesta:
Authorization: Bearer mcp_pat_XXXXXXXXXXXXXXXXXXXX2.2 OAuth 2.0 (Authorization Code + PKCE)
Per le applicazioni che gestiscono più account utente, usa il flusso OAuth 2.0 standard.
| Endpoint | URL |
|---|---|
| Discovery | https://api.cvforge.co/.well-known/oauth-authorization-server |
| Authorization | https://api.cvforge.co/oauth/authorize |
| Token exchange | https://api.cvforge.co/oauth/token |
| Revoca | https://api.cvforge.co/oauth/revoke |
2.3 Scope
| Scope | Descrizione |
|---|---|
| read:profile | Leggere il profilo, il piano e il saldo dei crediti |
| read:cv | Elencare, consultare e scaricare CV e generazioni |
| write:cv | Caricare CV, inviare offerte di lavoro e avviare ottimizzazioni |
3. Effettuare una chiamata MCP
L'API MCP usa il protocollo JSON-RPC 2.0 su HTTP. Ogni richiesta è un POST verso https://api.cvforge.co/mcp.
Formato di una richiesta
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXXXXXXXXXXXXXXXXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "<nom_de_l_outil>",
"arguments": { /* paramètres de l'outil */ }
}
}Formato di una risposta (successo)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{ ...données... }"
}
]
}
}Formato di una risposta (errore)
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32001,
"message": "Token invalide ou révoqué",
"data": { "error_code": "MCP_TOKEN_INVALID" }
}
}4. Strumenti disponibili
L'API espone 10 strumenti. Gli strumenti in lettura richiedono read:profile o read:cv. L'upload, l'invio di offerte e le ottimizzazioni richiedono write:cv.
get_profileread:profileRestituisce le informazioni dell'account: nome, email, piano di abbonamento.
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "get_profile", "arguments": {} }
}Risposta (estratto)
{
"id": "uuid",
"email": "alice@example.com",
"full_name": "Alice Martin",
"subscription_plan": "Expert",
"subscription_status": "active"
}get_creditsread:profileRestituisce il saldo dei crediti dettagliato (abbonamento, acquistati, gratuiti).
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "get_credits", "arguments": {} }
}Risposta (estratto)
{
"total": 7,
"subscription_credits": 5,
"paid_credits": 2,
"free_credits": 0
}list_cvsread:cvElenca i profili CV caricati (senza il contenuto).
Parametri
| Nome | Tipo | Descrizione |
|---|---|---|
| limit | integer? | Numero massimo (default: 20, max: 50) |
| offset | integer? | Paginazione (default: 0) |
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "list_cvs", "arguments": { "limit": 10, "offset": 0 } }
}Risposta (estratto)
{
"cvs": [
{
"id": "uuid",
"original_filename": "CV_Alice_2026.pdf",
"created_at": "2026-04-10T14:30:00Z",
"generation_count": 3
}
],
"total": 1
}get_cvread:cvRestituisce il contenuto completo (testo estratto) di un CV.
Parametri
| Nome | Tipo | Descrizione |
|---|---|---|
| cv_id | string | UUID del profilo CV |
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "get_cv", "arguments": { "cv_id": "uuid" } }
}Risposta (estratto)
{
"id": "uuid",
"original_filename": "CV_Alice_2026.pdf",
"extracted_text": "Alice Martin — Product Manager...",
"created_at": "2026-04-10T14:30:00Z"
}upload_cvwrite:cvCarica un CV in base64. Formati accettati: PDF, DOCX (max 10 MB). Restituisce il cv_profile_id da usare con optimize_cv.
Parametri
| Nome | Tipo | Descrizione |
|---|---|---|
| filename | string | Nome del file (con estensione) |
| file_base64 | string | Contenuto del file codificato in base64 |
| mime_type | string | application/pdf | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "upload_cv", "arguments": {
"filename": "mon_cv.pdf",
"file_base64": "JVBERi0xLjQ...",
"mime_type": "application/pdf"
} }
}Risposta (estratto)
{
"cv_profile_id": "uuid",
"message": "CV uploaded and parsed successfully."
}submit_offerwrite:cvInvia l'URL di un'offerta di lavoro (LinkedIn, Indeed, WTTJ, ecc.) per lo scraping e l'archiviazione. Restituisce l'offer_id da usare con optimize_cv. Limite: 5 chiamate/min. Siti supportati: LinkedIn, Indeed, WTTJ, France Travail, HelloWork, APEC, Cadremploi, Glassdoor, Meteojob, LeBonCoin, JobTeaser, Collective Work.
Parametri
| Nome | Tipo | Descrizione |
|---|---|---|
| offer_url | string | URL completo dell'offerta di lavoro |
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "submit_offer", "arguments": {
"offer_url": "https://www.linkedin.com/jobs/view/1234567890/"
} }
}Risposta (estratto)
{
"offer_id": "uuid",
"offer_url": "https://www.linkedin.com/jobs/view/1234567890/",
"job_title": "Product Manager Senior",
"company_name": "Acme Corp"
}optimize_cvwrite:cvAvvia l'ottimizzazione IA di un CV per un'offerta di lavoro. Consuma 1 credito. L'operazione è asincrona: usa get_generation per seguire l'avanzamento (pending → processing → completed/failed).
Parametri
| Nome | Tipo | Descrizione |
|---|---|---|
| cv_profile_id | string | UUID del profilo CV (ottenuto tramite upload_cv o list_cvs) |
| offer_id | string | UUID dell'offerta di lavoro (ottenuto tramite submit_offer) |
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "optimize_cv", "arguments": {
"cv_profile_id": "uuid-du-cv",
"offer_id": "uuid-de-l-offre"
} }
}Risposta (estratto)
{
"generation_id": "uuid",
"status": "processing",
"message": "CV optimization started"
}list_generationsread:cvElenca i CV ottimizzati generati, con il loro stato e i punteggi ATS.
Parametri
| Nome | Tipo | Descrizione |
|---|---|---|
| limit | integer? | Numero massimo (default: 20, max: 100) |
| offset | integer? | Paginazione (default: 0) |
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "list_generations", "arguments": { "limit": 5 } }
}Risposta (estratto)
{
"generations": [
{
"id": "uuid",
"cv_id": "uuid",
"job_title": "Product Manager Senior",
"ats_score": 87,
"status": "completed",
"created_at": "2026-04-11T09:00:00Z"
}
],
"total": 1
}get_generationread:cvRestituisce il dettaglio di una generazione: analisi, testo ottimizzato, punteggio.
Parametri
| Nome | Tipo | Descrizione |
|---|---|---|
| generation_id | string | UUID della generazione |
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "get_generation", "arguments": { "generation_id": "uuid" } }
}Risposta (estratto)
{
"id": "uuid",
"job_title": "Product Manager Senior",
"ats_score": 87,
"optimized_text": "Alice Martin — Product Manager Senior...",
"analysis": { "missing_keywords": ["OKR", "roadmap"], "strengths": [...] },
"status": "completed",
"created_at": "2026-04-11T09:00:00Z"
}download_generationread:cvScarica il PDF finale di una generazione in base64.
Parametri
| Nome | Tipo | Descrizione |
|---|---|---|
| generation_id | string | UUID della generazione |
Esempio di chiamata
POST https://api.cvforge.co/mcp
Content-Type: application/json
Authorization: Bearer mcp_pat_XXXX
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "download_generation", "arguments": { "generation_id": "uuid" } }
}Risposta (estratto)
{
"filename": "CV_Alice_PM_Senior.pdf",
"content_b64": "JVBERi0xLjQ...",
"mime_type": "application/pdf",
"size_bytes": 124580
}5. Esempi di integrazione
5.1 Flusso completo: upload → offerta → ottimizzazione → download
Esempio Python che illustra il percorso completo in 4 passaggi.
import requests, base64, time, json, os
PAT = os.environ["CVFORGE_PAT"]
MCP = "https://api.cvforge.co/mcp"
HEADERS = {"Content-Type": "application/json", "Authorization": f"Bearer {PAT}"}
def mcp(tool: str, args: dict = {}):
r = requests.post(MCP, json={
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": tool, "arguments": args}
}, headers=HEADERS, timeout=60)
r.raise_for_status()
data = r.json()
if "error" in data:
raise RuntimeError(data["error"]["message"])
return json.loads(data["result"]["content"][0]["text"])
# Étape 1 — Upload du CV
with open("mon_cv.pdf", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
cv = mcp("upload_cv", {
"filename": "mon_cv.pdf",
"file_base64": b64,
"mime_type": "application/pdf",
})
cv_id = cv["cv_profile_id"]
print(f"CV uploadé : {cv_id}")
# Étape 2 — Soumission de l'offre
offer = mcp("submit_offer", {
"offer_url": "https://www.linkedin.com/jobs/view/1234567890/"
})
offer_id = offer["offer_id"]
print(f"Offre : {offer['job_title']} @ {offer['company_name']} ({offer_id})")
# Étape 3 — Lancement de l'optimisation (1 crédit consommé)
gen = mcp("optimize_cv", {"cv_profile_id": cv_id, "offer_id": offer_id})
gen_id = gen["generation_id"]
print(f"Génération démarrée : {gen_id}")
# Étape 4 — Attente + téléchargement
for _ in range(20):
time.sleep(5)
details = mcp("get_generation", {"generation_id": gen_id})
print(f" statut : {details['status']}")
if details["status"] == "completed":
dl = mcp("download_generation", {"generation_id": gen_id})
print(f"Téléchargement : {dl['download_url']} (valide 15 min)")
break
if details["status"] == "failed":
raise RuntimeError("Optimisation échouée")5.2 curl
# Remplacez YOUR_PAT par votre Personal Access Token
export PAT="mcp_pat_XXXXXXXXXXXXXXXXXXXX"
# Récupérer le profil
curl -X POST https://api.cvforge.co/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $PAT" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_profile","arguments":{}}}'
# Vérifier le solde de crédits
curl -X POST https://api.cvforge.co/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $PAT" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_credits","arguments":{}}}'5.3 Claude Desktop / Claude.ai
Aggiungi il blocco seguente al tuo file di configurazione di Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json su macOS).
{
"mcpServers": {
"cvforge": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://api.cvforge.co/mcp",
"--header",
"Authorization: Bearer mcp_pat_XXXXXXXXXXXXXXXXXXXX"
]
}
}
}Dopo il riavvio, Claude avrà accesso agli strumenti CVforge direttamente nella conversazione. Di' per esempio: "Elenca i miei CV su CVforge" o "Carica il file MioCV.pdf su CVforge".
5.4 n8n — nodo HTTP Request
In n8n, crea un nodo HTTP Request con i seguenti parametri:
| Method | POST |
| URL | https://api.cvforge.co/mcp |
| Authentication | Header Auth · Name: Authorization · Value: Bearer mcp_pat_XXX |
| Content-Type | application/json |
| Body (JSON) | { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_cvs", "arguments": {} } } |
Il risultato JSON è disponibile nel nodo successivo tramite {{ $json.result.content[0].text }}. Analizzalo con un nodo Set o Function per estrarre i campi.
5.5 Cursor / Windsurf
In .cursor/mcp.json (o equivalente per Windsurf):
{
"mcpServers": {
"cvforge": {
"url": "https://api.cvforge.co/mcp",
"headers": {
"Authorization": "Bearer mcp_pat_XXXXXXXXXXXXXXXXXXXX"
}
}
}
}6. Codici di errore
| error_code | codice JSON-RPC | Descrizione |
|---|---|---|
| MCP_TOKEN_INVALID | -32001 | Token assente, malformato o revocato |
| MCP_TOKEN_EXPIRED | -32001 | Token scaduto — generane uno nuovo nelle Impostazioni |
| MCP_SUBSCRIPTION_REQUIRED | -32003 | Piano Expert richiesto — vedi /pricing |
| MCP_SCOPE_INSUFFICIENT | -32004 | Il token non possiede lo scope necessario |
| MCP_TOOL_NOT_FOUND | -32601 | Strumento sconosciuto |
| MCP_INVALID_PARAMS | -32602 | Parametri non validi o mancanti |
| MCP_INTERNAL_ERROR | -32603 | Errore interno — riprova o contatta il supporto |
| PARSE_ERROR | -32700 | JSON non valido nella richiesta |
| INVALID_REQUEST | -32600 | Struttura JSON-RPC non valida |
7. Limiti e buone pratiche
Rate limiting
| Limite | Valore |
|---|---|
| Richieste al minuto (per IP) | 60 req/min |
| submit_offer (per utente) | 5 req/min |
| Dimensione massima di un file caricato | 10 MB |
| Formati CV accettati | PDF, DOCX |
| Token PAT attivi contemporaneamente | 10 per account |
In caso di superamento, l'API restituisce un HTTP 429 con l'header Retry-After. Implementa un backoff esponenziale nelle tue automazioni.
Buone pratiche
- Crea un token per ogni integrazione (uno per n8n, uno per Claude Desktop…) — così puoi revocarne uno singolarmente senza impattare gli altri.
- Concedi a ogni token solo gli scope necessari.
- Conserva i token in variabili d'ambiente o in un gestore di segreti, mai hardcoded nel codice.
- Revoca immediatamente qualsiasi token compromesso dalla pagina Impostazioni.
- L'endpoint MCP supporta CORS aperto — ricordati di validare l'origine lato server nelle tue integrazioni.
Rilevabilità
CVforge pubblica un manifest MCP leggibile dagli LLM e dai motori di ricerca:
- /.well-known/mcp.json — manifest MCP
- /.well-known/oauth-authorization-server — discovery OAuth2 (RFC 8414)
- /llms.txt — contesto MCP per gli LLM
Pronto a integrare CVforge?
Crea il tuo primo token in 30 secondi dalle Impostazioni.