Documentazione API
Tutto ciò che trovi di seguito è generato dalle stesse definizioni utilizzate dal motore, quindi non può descrivere funzionalità di cui il codice è privo.
Descrizione OpenAPI leggibile da macchine: /api/v1/openapi.json
Autenticazione
Invia la tua chiave in uno dei due header. Entrambi sono equivalenti.
Authorization: Bearer nmd_live_xxxxxxxxxxxxxxxx X-API-Key: nmd_live_xxxxxxxxxxxxxxxx
Le chiavi si creano nella tua dashboard. Una chiave viene mostrata una sola volta e memorizzata solo come hash: se la perdi, revocala e creane un’altra.
POST /api/v1/analyze
Legge ogni campo di metadati presente nel file e restituisce il modello normalizzato.
curl -X POST https://your-domain/api/v1/analyze \ -H "Authorization: Bearer $NMD_KEY" \ -F "file=@photo.jpg"
La risposta raggruppa i campi per categoria e mantiene i valori originali non tradotti sotto raw:
{
"file": { "name": "photo.jpg", "format": "jpeg", "size": 4821904 },
"counts": { "total": 31, "removable": 26, "sensitive": 16 },
"blocks": { "exif": { "present": true, "count": 29 }, "gps": { "present": true } },
"metadata": {
"camera": {
"camera.make": { "label": "Make", "value": "Apple", "sensitive": true, "removable": true }
}
}
}POST /api/v1/clean
Rimuove i metadati, quindi rilegge i byte prodotti per verificare il risultato. Restituisce il file pulito per impostazione predefinita, oppure il solo report con <code>response=json</code>.
| Parametro | Valori | Predefinito |
|---|---|---|
| mode | quick, full | quick |
| keepCopyright | 0, 1 | 0 |
| keepColorProfile | 0, 1 | quick: 1, full: 0 |
| keepOrientation | 0, 1 | quick: 1, full: 0 |
| removeC2pa | 0, 1 | 0 |
| response | file, json | file |
curl -X POST https://your-domain/api/v1/clean \ -H "Authorization: Bearer $NMD_KEY" \ -F "file=@video.mp4" -F "mode=full" -OJ
removeC2pa è disattivato per impostazione predefinita e non viene attivato da mode=full. Una normale pulizia dei metadati non rimuove mai le Content Credentials C2PA: cancellare la storia di provenienza di un file è un’istruzione distinta che il chiamante deve richiedere esplicitamente.
Quando viene restituito un file, nell’header X-NoMoreData-Result viaggia codificato in URL un riepilogo del report di verifica: i valori scalari testuali — verified è true solo quando la ri-analisi non ha riscontrato residui inattesi — e ogni elenco come conteggio, removedCount, residualCount e così via. Si decodifica e si analizza sempre. Per gli elenchi stessi, chiedi response=json.
POST /api/v1/edit
Applica modifiche ai campi. <code>value: null</code> elimina un campo. I campi al di fuori del registro scrivibile vengono segnalati in <code>warnings</code> anziché essere scartati silenziosamente.
| Parametro | Valori | Predefinito |
|---|---|---|
| edits | JSON array of {key, value} | required |
| replaceAll | 0, 1 | 0 |
| removeC2pa | 0, 1 | 0 |
| response | file, json | file |
replaceAll rimuove i blocchi di metadati esistenti. Non rimuove le Content Credentials C2PA: per quello c’è removeC2pa, disattivato per impostazione predefinita. Se sostituisci tutto lasciando la credenziale, la risposta lo indica chiaramente.
curl -X POST https://your-domain/api/v1/edit \
-H "Authorization: Bearer $NMD_KEY" \
-F "file=@photo.jpg" \
-F 'edits=[{"key":"camera.make","value":"Canon"},{"key":"location.latitude","value":null}]' \
-F "response=json"POST /api/v1/apply-profile
Scrive un set coerente di campi tipici di un dispositivo. Gli ID dei profili si ottengono da <code>GET /api/profiles</code>.
curl -X POST https://your-domain/api/v1/apply-profile \ -H "Authorization: Bearer $NMD_KEY" \ -F "file=@photo.jpg" -F "profile=canon-eos-r5" -F "iso=400"
L’applicazione di un profilo scrive metadati tipici di un dispositivo. Non attesta e non può attestare che il file abbia avuto origine da tale dispositivo: i metadati sono modificabili per progettazione e non costituiscono una prova di provenienza. Ogni risposta include questo disclaimer.
Altri linguaggi
JavaScript
const body = new FormData();
body.append('file', file); // a File or Blob
body.append('mode', 'full');
body.append('response', 'json');
const res = await fetch('https://your-domain/api/v1/clean', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.NMD_KEY}` },
body,
});
const report = await res.json();
console.log(report.verified, report.removed.length);Python
import os, requests
with open("photo.jpg", "rb") as fh:
response = requests.post(
"https://your-domain/api/v1/clean",
headers={"Authorization": f"Bearer {os.environ['NMD_KEY']}"},
files={"file": fh},
data={"mode": "full", "response": "json"},
)
report = response.json()
print(report["verified"], len(report["removed"]))Errori
Tutti gli errori condividono la stessa struttura e non espongono mai dettagli interni né tracce dello stack.
{ "error": { "code": "unsupported_format", "message": "GIF is not supported.", "hint": "..." } }| Codice | Stato HTTP | Significato |
|---|---|---|
| missing_api_key | 401 | Nessuna chiave API fornita. |
| invalid_api_key | 401 | La chiave è sconosciuta, revocata o non valida. |
| plan_required | 403 | Il tuo piano attuale non include l’accesso alle API. |
| missing_file | 400 | Nessun file presente nella richiesta multipart. |
| invalid_request | 400 | Un parametro era mancante o malformato. |
| file_too_large | 413 | Il file supera il limite di dimensione consentito dal tuo piano. |
| unsupported_format | 415 | Il formato del file non è supportato. |
| corrupt_file | 422 | Impossibile analizzare il file: potrebbe essere danneggiato. |
| unsupported_operation | 422 | File valido, ma l’operazione richiesta non è implementata per questo formato. |
| rate_limited | 429 | Troppe richieste in un breve intervallo di tempo. |
| quota_exceeded | 429 | Hai esaurito la quota di chiamate mensili prevista dal tuo piano. |
Limiti di frequenza e quote
Si applicano due limiti: un rate limit a breve termine per indirizzo IP per proteggere il servizio e la quota mensile di chiamate prevista dal tuo piano. Le risposte andate a buon fine includono la quota rimanente.
X-RateLimit-Limit: 2000 X-RateLimit-Remaining: 1834 X-RateLimit-Reset: 1767225600
Un rifiuto per superamento quota restituisce HTTP 429 con codice quota_exceeded e un header Retry-After. L’utilizzo viene conteggiato solo per le richieste che hanno effettivamente eseguito lavoro: una richiesta rifiutata non consuma la tua quota.
Formati supportati
| Formato | Analizza | Pulisci | Modifica |
|---|---|---|---|
| JPEG | sì | sì | sì |
| PNG | sì | sì | sì |
| WebP | sì | sì | sì |
| HEIC/HEIF | sì | sì | sì |
| AVIF | sì | sì | sì |
| MP4 | sì | sì | sì |
| QuickTime MOV | sì | sì | sì |
| WebM | sì | sì | no |
| sì | sì | sì | |
| MP3 | sì | sì | sì |
| WAV | sì | sì | sì |
| M4A | sì | sì | sì |
Un’operazione non implementata per un formato restituisce 422 unsupported_operation invece di restituire il file invariato.
Campi scrivibili (28)
Chiavi accettate da /api/v1/edit. Ciascuna di esse è supportata da un encoder dedicato.
| Chiave | Campo |
|---|---|
| camera.make | Make |
| camera.model | Model |
| camera.lensMake | Lens make |
| camera.lensModel | Lens model |
| camera.serialNumber | Body serial number |
| camera.lensSerialNumber | Lens serial number |
| capture.iso | ISO |
| capture.exposureTime | Exposure time |
| capture.fNumber | Aperture (f-number) |
| capture.focalLength | Focal length |
| capture.focalLength35mm | Focal length (35 mm equiv.) |
| capture.exposureBias | Exposure compensation |
| capture.exposureProgram | Exposure program |
| capture.meteringMode | Metering mode |
| capture.whiteBalance | White balance |
| capture.flash | Flash |
| capture.colorSpace | Colour space |
| capture.orientation | Orientation |
| date.original | Date taken |
| date.digitized | Date digitised |
| date.modified | File change date |
| general.software | Software |
| general.artist | Artist |
| general.copyright | Copyright |
| general.description | Image description |
| location.latitude | Latitude |
| location.longitude | Longitude |
| location.altitude | Altitude |
Come vengono gestiti i tuoi file
Un file inviato all’API viene mantenuto in memoria per la sola durata della richiesta, utilizzato unicamente per l’operazione desiderata e rilasciato insieme alla risposta. Nulla viene memorizzato su disco, archiviato, registrato o impiegato per addestramento o statistiche.
Questo si differenzia dal sito web, che elabora i file interamente nel browser senza caricare nulla. Se la tua integrazione può essere eseguita lato client, quella rimane l’opzione consigliata per la massima riservatezza.