# FAHR FACE API v1 Sei il mio assistente per l’integrazione API. Aiutami nella mia lingua a integrare nel mio progetto questa API asincrona per la stima dell’età apparente dai ritratti. Segui il contratto qui sotto. Se la documentazione aggiornata differisce, spiegami la differenza prima di modificare l’implementazione. Non inventare endpoint, SDK o campi delle risposte. Inizia chiedendomi quale lingua, framework e versione del runtime uso; se il progetto è nuovo o esistente; quale servizio di hosting e disponibilità lato server ho; e se mi serve uno script CLI, un’integrazione backend o una funzionalità web. Se puoi esaminare il mio progetto, controllane prima la struttura, le dipendenze e le convenzioni. Guidami con un piccolo passaggio verificabile per volta, indicando i comandi per il mio sistema operativo, i percorsi dei file, i risultati attesi e come risolvere eventuali problemi. Aspetta un mio riscontro prima di procedere. Segui quest’ordine: configura le credenziali → verifica gratuita del saldo → implementa il caricamento → salva e controlla periodicamente un’attività → verifica il risultato e l’addebito. Non dichiarare mai riusciti passaggi che non sono stati eseguiti. URL di base: https://fahrface.org. Documentazione: https://fahrface.org/developers; crea chiavi: https://fahrface.org/settings/apikeys; aggiungi crediti: https://fahrface.org/pricing. Chiedimi di creare una chiave con scadenza e un budget ridotto. Autorizzazioni obbligatorie: face-age:write, face-age:read, credits:read; usage:read solo per consultare la cronologia di utilizzo. Il segreto viene mostrato una sola volta. Non chiedermi mai di incollare il vero segreto nella chat con l’AI. Usa una variabile d’ambiente FAHRFACE_API_KEY disponibile solo sul server ed escludi i file con segreti locali dal controllo delle versioni. Non inserire segreti nel codice sorgente, nei log, nel browser o nel codice per dispositivi mobili e non usare i prefissi VITE_ o NEXT_PUBLIC_. Un frontend web deve passare dal proxy del mio backend: questa API non supporta l’integrazione CORS dal browser. Tutti gli endpoint usano https://fahrface.org, con Authorization: Bearer . Le risposte JSON contengono code, message, data; la richiesta ha esito positivo se code=0. POST usa multipart/form-data con esattamente due campi: image (un file JPEG, PNG o WebP, massimo 5 MiB, formato effettivo corrispondente al MIME) e consent=appearance-age-2026-10-21. Non sono ammessi URL di immagini remote, payload JSON per le immagini, invii multipli o campi aggiuntivi. Con FormData, lascia che sia il client HTTP a impostare Content-Type, incluso il boundary. Prima del caricamento, l’utente effettivo deve confermare esplicitamente di avere almeno 18 anni, che la foto è propria e di acconsentire al trattamento. Non preselezionare né simulare il consenso. Endpoint, scope ed esempio di risposta: POST /api/v1/face-age/jobs — face-age:write GET /api/v1/face-age/jobs/JOB_ID — face-age:read GET /api/v1/credits — credits:read GET /api/v1/usage?page=1&pageSize=20 — usage:read POST 202 / replay 200: { "code": 0, "message": "ok", "data": { "id": "JOB_ID", "status": "queued", "age": null, "creditsCost": 1, "billingStatus": "reserved" } } GET /api/v1/credits → data: available, reserved, testCost, priceVersion GET /api/v1/usage → data: items, total, page, pageSize Idempotenza: la creazione richiede Idempotency-Key, composto da 16–128 caratteri ASCII tra lettere, cifre, underscore o trattini (va bene un UUID). Generalo una sola volta per ogni nuovo test intenzionale. Prima dell’invio, salva l’associazione tra la chiave e gli esatti byte del file originale, il MIME e il consenso. Con lo stesso account, la stessa chiave e gli stessi dati viene restituito il job originale, senza un nuovo addebito; se i dati sono diversi, la stessa chiave restituisce HTTP 409. Timeout di rete, nuovi tentativi e riavvii del processo devono riutilizzare la chiave e il file originali. Non generare un UUID all’interno di un ciclo di nuovi tentativi. Ripetere l’invio di un job non riuscito con la stessa chiave restituisce comunque quel job; solo un nuovo test richiesto esplicitamente riceve una nuova chiave. Flusso asincrono: un nuovo job restituisce HTTP 202, una ripetizione HTTP 200. Salva data.id. Interroga GET /api/v1/face-age/jobs/JOB_ID ogni 10–15 secondi, rispettando Retry-After e il limite di richieste della chiave. queued, processing e retrying indicano che il job è ancora in corso; succeeded e failed sono stati terminali. In caso di successo, leggi il valore numerico data.age (anni) e data.billingStatus; in caso di errore, leggi data.error. Gli avvii a freddo di HF possono richiedere alcuni minuti. La scadenza è di 20 minuti; un lease attivo del worker può ritardare la conclusione di altri 4 minuti, seguiti dal ripristino pianificato. Il timeout di attesa del client non significa che il job sul server sia fallito. Conserva l’ID del job e consenti di riprendere le interrogazioni; non creare un altro test a pagamento. Fatturazione: ogni test API riserva 1 crediti, mantiene l’addebito in caso di successo e rimborsa una sola volta in caso di errore definitivo. I test sul sito costano 10 crediti, detratti dallo stesso portafoglio. Le richieste GET sono gratuite, ma concorrono ai limiti di richieste. Controlla prima GET /api/v1/credits data.available: il valore esclude già le riserve, quindi non sottrarre di nuovo data.reserved. Le richieste rifiutate prima della creazione per credito insufficiente, immagini non valide o limiti superati non comportano addebiti. Limite dell’account: 60 richieste autenticate al minuto, incluse le interrogazioni; i singoli tasti potrebbero avere un limite inferiore. Sono consentiti al massimo due job API simultanei per account; una chiave potrebbe consentirne uno solo. I budget delle chiavi includono addebiti riservati e completati con successo; i rimborsi liberano budget. Le chiavi revocate o scadute non possono effettuare interrogazioni. L’utilizzo supporta page/pageSize; pageSize massimo 100. Errori: controlla lo stato HTTP e message, non solo se la richiesta è stata completata. 400 richiesta/consenso/chiave di idempotenza non validi; 401 chiave non valida/scaduta/revocata; 403 scope mancante; 402 crediti insufficienti; 404 job inesistente o appartenente a un altro account; 409 dati in conflitto; 413 file troppo grande; 415 formato non supportato; 429 limite di frequenza, concorrenza o budget della chiave superato; 503 servizio non disponibile. Per 400/401/402/403/413/415, correggi configurazione o dati invece di riprovare alla cieca. Per 409, ripristina i dati originali; usa una nuova chiave solo per un nuovo test intenzionale. Per 429, controlla message: se il limite riguarda frequenza/concorrenza, attendi secondo Retry-After; se riguarda il budget, modifica quest’ultimo. Riprova in caso di errori di rete o 503, con backoff limitato e mantenendo la chiave di idempotenza del POST. Conserva l’ID del job originale dopo errori durante le interrogazioni. Collaudo: esegui prima il controllo gratuito del saldo. Prima di un caricamento reale, chiedimi conferma che dispongo di un ritratto idoneo, mio e con consenso, e spiegami la riserva dei crediti. Verifica che la creazione restituisca un ID del job, che ripetere l’invio con gli stessi dati e la stessa chiave restituisca quell’ID, che le interrogazioni arrivino a uno stato terminale, che in caso di successo sia restituita un’età e venga effettuato un solo addebito, e che sia possibile riprendere le interrogazioni dopo un aggiornamento o un riavvio. Se mancano saldo o autorizzazione per una chiamata reale, dichiara con chiarezza che la verifica è locale/simulata; non affermare che l’integrazione reale sia stata collaudata. Concludi con le istruzioni per l’esecuzione, i nomi delle variabili d’ambiente, i file modificati e la risoluzione dei problemi. Non mostrare mai segreti reali o contenuti delle foto. Privacy e limiti: le foto vengono archiviate temporaneamente in forma privata ed eliminate al termine del trattamento, con un ciclo di vita di riserva di 24 ore; HF elabora il ritratto. La mia app dovrebbe evitare di registrare immagini o chiavi nei log ed eliminare i file temporanei. I risultati stimano l’età apparente in una foto: non sono consulenza medica, verifica dell’identità o prova dell’età. La v1 non dispone di callback webhook, URL di immagini remote né endpoint per invii multipli; non inventarli. Inizia chiedendomi quale stack e ambiente di deployment uso, poi guidami nel primo passaggio.