Documentazione API
API PhotoFig
Metti in coda modifiche e ridimensionamenti delle immagini prodotto, applica modelli a interi lotti, segui l'avanzamento e ricevi eventi webhook firmati con chiavi API.
Hai bisogno di uno schema leggibile dal computer? Scarica il file JSON di OpenAPI.
In questa pagina
Guida rapida
Crea una chiave API in Impostazioni. Sostituisci YOUR_API_KEY qui sotto e salva una foto come product.jpg.
Invia una foto
Carica la foto per aggiungere un’ombra al prodotto. La risposta contiene un ID del job e statusUrl.
curl https://api.photofig.com/v1/tools/ai-shadows/edit \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "image=@product.jpg"Controlla il job
Sostituisci STATUS_URL con il valore statusUrl ricevuto. Se status è queued o processing, attendi prima di controllare di nuovo.
curl "STATUS_URL" \ -H "Authorization: Bearer YOUR_API_KEY"Scarica il risultato
Quando status è completed, sostituisci RESULT_URL con il valore resultUrl ricevuto per salvare l’immagine.
curl -fL "RESULT_URL" -o photofig-result.png
Usa i Webhook per ricevere automaticamente gli eventi di completamento.
Autenticazione
I percorsi API accettano chiavi API generate da Impostazioni. La chiave segreta completa viene visualizzata una sola volta al momento della creazione della chiave.
Authorization: Bearer pf_live_...Le chiavi API funzionano solo con gli endpoint di questa pagina; tutte le altre route di PhotoFig le rifiutano. Una chiave agisce per la persona che l'ha creata, nel workspace in cui è stata creata.
Limiti e quote
L'accesso API è incluso in Pro e Studio. GET /v1/account mostra i limiti del tuo piano, inclusa la quota oraria di richieste in limits.rateLimitPerHour.
Ogni richiesta autenticata conta per la quota oraria, compresa la verifica dello stato dei job. Le risposte includono X-RateLimit-Limit e X-RateLimit-Remaining. Esaurita la quota, l'API risponde 429 rate_limit_exceeded con un header Retry-After.
mask usa rimozioni dello sfondo, ai-bg e ai-shadows un credito IA ciascuno, resize nessuno dei due. I crediti vengono addebitati solo quando un job viene completato.
I job in coda o in esecuzione contano per il limite di job simultanei del tuo piano. Oltre quel limite, le nuove modifiche ricevono 429 too_many_jobs finché i job precedenti non terminano.
POST /v1/uploads e POST /v1/tools/{tool_id}/edit accettano un header facoltativo X-Idempotency-Key. Un nuovo tentativo con la stessa chiave restituisce la prima risposta invece di avviare un secondo job, quindi usa una chiave nuova per ogni richiesta distinta.
Account
/v1/accountUtilizza questo percorso per eseguire un test di verifica delle credenziali e per controllare i limiti del piano, i crediti rimanenti e gli strumenti disponibili.
{
"accountId": "uuid",
"workspaceId": "uuid",
"plan": "pro",
"apiEnabled": true,
"credits": {
"remaining": 2000,
"bonusRemaining": 0,
"periodEndsAt": "2026-11-01T00:00:00Z"
},
"limits": {
"maxFileSizeBytes": 10485760,
"rateLimitPerHour": 60,
"concurrentJobs": 3,
"maxApiKeys": 1,
"freeBgRemovals": 0,
"bgRemovalsUsed": 0,
"aiCredits": 2000
},
"tools": [
"mask",
"ai-bg",
"ai-shadows",
"resize"
]
}Strumenti
/v1/tools/v1/tools/{tool_id}Ogni strumento accetta una normale immagine prodotto tramite imageUrl, uploadSessionId o un caricamento multipart. Non serve chiamare prima mask: ai-bg e ai-shadows rimuovono lo sfondo da soli.
mask
Rimuove lo sfondo e restituisce il prodotto scontornato in un PNG trasparente. Usalo per isolare il prodotto prima della composizione o dell’elaborazione destinata a una piattaforma di vendita.
ai-shadows
Aggiunge un'ombra realistica al prodotto e restituisce un'immagine pronta per uno sfondo pulito. Funziona al meglio quando il prodotto è ben visibile e non è nascosto da una scena troppo affollata.
ai-bg
Genera un nuovo sfondo per il prodotto a partire da un breve tema, ad esempio warm oak tabletop oppure minimal white studio. Invia direttamente l’immagine del prodotto; non è necessaria una richiesta separata per la rimozione dello sfondo.

resize
Adatta una foto a una dimensione esatta della tela mantenendo il suo sfondo, come “Ridimensiona foto” nell'app. Scegli adatta o riempi, la posizione e il riempimento. Non usa crediti IA.
Carica e modifica in un'unica operazione
/v1/tools/{tool_id}/editQuesto è il metodo più semplice: invia una modifica con un `imageUrl` quando l’immagine di origine è già raggiungibile tramite URL, oppure invia un campo immagine multipart per una rapida richiesta di file locale. È l’opzione migliore quando devi eseguire un solo strumento su un unico input.
Scegli questa opzione quando hai una sola immagine, una sola modifica e non hai bisogno di riutilizzare la fonte caricata.
curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
-H "Authorization: Bearer pf_live_..." \
-F "image=@product.jpg" \
-F "seed=128742"Carica prima, modifica dopo
/v1/uploadsCrea una sessione di caricamento per inviare i dati dell'immagine direttamente allo storage, poi avvia una modifica con l'uploadSessionId restituito. Il limite di dimensione è lo stesso di una richiesta multipart e ogni sessione serve per una sola modifica.
Scegli questa strada quando il client non deve far passare l'immagine dalla richiesta di modifica, ad esempio un browser che carica direttamente nello storage.
UPLOAD_JSON=$(curl -s -X POST https://api.photofig.com/v1/uploads \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"contentType": "image/jpeg",
"filename": "product.jpg",
"sizeBytes": 1842031
}')
curl -X PUT "$(echo "$UPLOAD_JSON" | jq -r '.uploadUrl')" \
-H "Content-Type: image/jpeg" \
--data-binary @product.jpg
curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d "{
\"uploadSessionId\": \"$(echo "$UPLOAD_JSON" | jq -r '.uploadSessionId')\",
\"parameters\": { \"seed\": 128742 }
}"Crea modifiche
/v1/tools/{tool_id}/editInvia modifiche con imageUrl, uploadSessionId o un campo multipart image. La risposta restituisce un ID job per verifica dello stato, annullamento, eliminazione e abbinamento con gli eventi webhook. I parametri che uno strumento non usa vengono ignorati.
Contesto dell'IA
L'endpoint di sfondo basato sull'IA funziona al meglio con un tema conciso della scena: un'ambientazione, una superficie, un'indicazione di illuminazione o un'atmosfera descritta in poche parole. Alcuni buoni esempi includono warm oak tabletop,minimal white studio, and soft morning kitchen light.
curl -X POST https://api.photofig.com/v1/tools/ai-bg/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.example.com/product.png",
"parameters": {
"theme": "warm oak tabletop",
"seed": 128742
}
}'Product Shadow
curl -X POST https://api.photofig.com/v1/tools/ai-shadows/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.example.com/product.png",
"parameters": { "seed": 128742 }
}'Maschera
mask non ha parametri e restituisce un ritaglio PNG con trasparenza.
curl -X POST https://api.photofig.com/v1/tools/mask/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.example.com/product.png"
}'Ridimensiona
width e height impostano l'output in pixel, da 100 a 4096. mode è fit (tutta la foto, predefinito), fill (copre la tela e ritaglia l'eccedenza), width o height. horizontal e vertical posizionano la foto e background riempie lo spazio libero: transparent, un colore #RRGGBB o un oggetto sfumatura. Il risultato è un PNG.
curl -X POST https://api.photofig.com/v1/tools/resize/edit \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.example.com/product.jpg",
"parameters": {
"width": 1000,
"height": 1000,
"mode": "fit",
"background": "#ffffff"
}
}'Attività
/v1/jobs/v1/jobs/{job_id}/v1/jobs/{job_id}/cancel/v1/jobs/{job_id}Elenca, verifica, annulla o elimina le attività API. Le attività API non compaiono nelle sezioni «Caricamenti» o «Progetti» dopo l’accesso; eliminandole vengono rimossi anche i relativi file.
GET /v1/jobs/{job_id} restituisce lo stato del job. Quando è completato, scarica l'immagine da resultUrl prima di expiresAt. Ogni verifica conta per la tua quota oraria; usa i webhook per ricevere gli eventi di completamento.
{
"id": "api_edit_uuid",
"tool": "ai-shadows",
"status": "completed",
"createdAt": "2026-07-15T10:15:00Z",
"startedAt": "2026-07-15T10:15:04Z",
"finishedAt": "2026-07-15T10:15:23Z",
"statusUrl": "https://api.photofig.com/v1/jobs/api_edit_uuid",
"resultUrl": "https://storage.example.com/signed-result-url",
"thumbnailUrl": "https://storage.example.com/signed-thumbnail-url",
"expiresAt": "2026-07-15T11:15:23Z",
"error": null
}Modelli
/v1/templates/v1/templates/v1/templates/{template_id}/v1/templates/{template_id}/v1/templates/{template_id}Un modello è uno stile da applicare a molte foto: rimozione dello sfondo, posizionamento, sfondo e ombra, margine e dimensioni di esportazione. I modelli creati tramite API si aprono e si modificano nell'app PhotoFig, e viceversa. I modelli di sistema sono pronti all'uso e di sola lettura.
mask e resize sono obbligatori; gli altri passaggi sono facoltativi e seguono un ordine fisso. Passaggi o campi sconosciuti vengono rifiutati e i valori devono rientrare negli intervalli offerti dall'editor. Lo schema OpenAPI elenca ogni campo.
curl -X POST https://api.photofig.com/v1/templates \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Cream catalog",
"steps": {
"mask": {},
"reposition": { "horizontal": "center", "vertical": "center", "scale": 0.85 },
"background": { "backgroundType": "solid", "color": "#f6f1ea" },
"ai-shadows": { "opacity": 0.8 },
"resize": { "mode": "fit", "targets": [{ "width": 2000, "height": 2000 }] }
},
"export": { "format": "jpg", "background": "#ffffff" }
}'creditsPerPhoto è quanto il modello addebita per ogni foto, ad esempio un credito IA per ai-shadows.
Lotti
/v1/batches/v1/batches/{batch_id}/uploads/v1/batches/{batch_id}/uploads/{upload_id}/complete/v1/batches/{batch_id}/process/v1/batches/{batch_id}/v1/batches/v1/batches/{batch_id}/cancel/v1/batches/{batch_id}Un lotto applica un modello a molte foto. Crealo, aggiungi le foto, poi elaboralo con un modello. Le foto mantengono la posizione che dai loro.
Ogni foto va direttamente nello storage: richiedi un caricamento, invia i byte con PUT a uploadUrl, poi completalo.
BATCH_ID=$(curl -s -X POST https://api.photofig.com/v1/batches \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Spring arrivals" }' | jq -r '.id')
# For each photo: ask for an upload, PUT the bytes, complete it.
UPLOAD=$(curl -s -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/uploads" \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{ "filename": "boots.jpg", "contentType": "image/jpeg", "sizeBytes": 1842031, "position": 0 }')
curl -X PUT "$(echo "$UPLOAD" | jq -r '.uploadUrl')" \
-H "Content-Type: image/jpeg" --data-binary @boots.jpg
curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/uploads/$(echo "$UPLOAD" | jq -r '.uploadId')/complete" \
-H "Authorization: Bearer pf_live_..."
curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/process" \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{ "templateId": "TEMPLATE_ID" }'Sapere quando un lotto è finito
Registra una volta un webhook per batch.completed invece di interrogare. PhotoFig lo chiama alla fine di ogni lotto, con l'ID del lotto e quante foto sono riuscite o fallite.
curl -X POST https://api.photofig.com/v1/webhooks \
-H "Authorization: Bearer pf_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/photofig/webhooks",
"events": ["batch.completed"]
}'{
"event": "batch.completed",
"eventId": "uuid",
"createdAt": "2026-10-06T12:00:00Z",
"data": {
"batchId": "uuid",
"status": "completed",
"totalItems": 12,
"completedItems": 12,
"failedItems": 0
}
}Quando arriva batch.completed, leggi il lotto. Ogni foto finita ha un link di anteprima fino a 1024 pixel. Rimozioni dello sfondo e crediti IA vengono addebitati come nell'app.
{
"id": "uuid",
"name": "Spring arrivals",
"status": "completed",
"templateName": "Cream catalog",
"totalItems": 2,
"completedItems": 2,
"failedItems": 0,
"resultsAvailableUntil": "2026-10-20T12:00:00Z",
"items": [
{
"id": "uuid",
"position": 0,
"filename": "boots.jpg",
"status": "completed",
"width": 3024,
"height": 4032,
"preview": {
"url": "https://...",
"width": 1024,
"height": 1024
}
}
]
}Scaricare i risultati
/v1/batches/{batch_id}/items/{item_id}/download/v1/batches/{batch_id}/download-urlScarica ogni risultato a dimensione reale nel formato di esportazione del modello, oppure l'intero lotto come ZIP. Ogni risultato conta una volta come esportazione, come nell'app; riscaricarlo è gratuito.
Condividere i risultati
/v1/batches/{batch_id}/share/v1/batches/{batch_id}/share/v1/batches/{batch_id}/shareUn link di condivisione è una pagina pubblica con anteprime prima/dopo e download ZIP, senza accesso. Un lotto ha un solo link: richiederlo di nuovo restituisce lo stesso, e revocarlo lo chiude subito. I download dalla pagina contano come tue esportazioni, e la pagina funziona fino a availableUntil. La condivisione richiede un piano a pagamento.
curl -X POST "https://api.photofig.com/v1/batches/$BATCH_ID/share" \
-H "Authorization: Bearer pf_live_..."{
"url": "https://photofig.com/share/TOKEN",
"availableUntil": "2026-10-20T12:00:00Z",
"createdAt": "2026-10-06T12:05:00Z",
"downloadCount": 0
}Webhook
I webhook permettono a PhotoFig di avvisare il tuo server quando un job API termina, fallisce o viene annullato, e quando un lotto è completato, così il tuo backend non deve interrogare. Registra un URL HTTPS su un host pubblico. Un endpoint riceve gli eventi dei job e dei lotti creati con le chiavi API del suo proprietario.
/v1/webhooks/v1/webhooks/v1/webhooks/{webhook_id}/v1/webhooks/{webhook_id}/v1/webhooks/{webhook_id}/v1/webhooks/{webhook_id}/testGli eventi supportati sono webhook.test,job.completed,job.failed,job.cancelled, e batch.completed. Gli eventi dei job usano l'ID del job restituito alla creazione della modifica; batch.completed contiene l'ID del lotto.
{
"event": "job.completed",
"eventId": "uuid",
"createdAt": "2026-07-15T10:15:23Z",
"data": {
"id": "api_edit_uuid",
"tool": "ai-shadows",
"status": "completed",
"resultUrl": "https://storage.example.com/signed-result-url",
"thumbnailUrl": "https://storage.example.com/signed-thumbnail-url",
"expiresAt": "2026-07-15T11:15:23Z"
}
}Verifica ogni consegna
Ogni richiesta include PhotoFig-Webhook-Timestamp e PhotoFig-Webhook-Signature. Calcola con il secret dell'endpoint un HMAC-SHA256 del timestamp, di un punto e del corpo grezzo della richiesta, e confrontalo con il valore dopo v1=. Rifiuta i timestamp più vecchi di qualche minuto. Il secret viene mostrato solo alla creazione dell'endpoint.
import crypto from 'node:crypto';
// rawBody is the request body exactly as received, before JSON parsing.
export function verifyPhotoFigWebhook(headers, rawBody, secret) {
const timestamp = headers['photofig-webhook-timestamp'];
const signature = headers['photofig-webhook-signature'] ?? '';
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = 'v1=' + crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return signature.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Rispondi con qualsiasi stato 2xx entro 10 secondi. Le altre risposte vengono ritentate dopo 1 minuto, 5 minuti, 30 minuti, 2 ore e 12 ore. PhotoFig-Webhook-Id resta uguale tra i tentativi, usalo per ignorare i duplicati. I link di download nel payload vengono firmati a ogni tentativo e smettono di funzionare quando il risultato scade.
Errori
Le risposte di errore includono un codice stabile leggibile dal software e un messaggio per l’utente. Usa il codice per gestire i diversi casi nella logica del client.
{
"code": "invalid_request",
"message": "imageUrl or uploadSessionId is required"
}Codici comuni
invalid_request- Un parametro manca o non è valido; il messaggio indica quale.
api_key_not_allowed- È stata usata una chiave API su una route esterna all'API pubblica.
api_access_disabled- Il piano del workspace non include l'accesso API.
insufficient_funds- Per questo strumento non restano crediti IA o rimozioni dello sfondo.
rate_limit_exceeded- La quota oraria di richieste è esaurita; attendi Retry-After.
too_many_jobs- Troppi job in coda o in esecuzione; riprova quando i precedenti terminano.
tool_unavailable- I worker dello strumento sono brevemente non disponibili; riprova a breve.
webhook_limit_reached- Il proprietario della chiave ha raggiunto il limite di endpoint webhook per questo workspace.
Durata dei risultati
I job API completati restano visibili tramite GET /v1/jobs e GET /v1/jobs/{job_id}. La risposta di stato contiene link resultUrl e thumbnailUrl firmati finché i risultati sono disponibili.
I file delle attività API vengono archiviati separatamente dai caricamenti e dai progetti creati nell’editor. Non vengono visualizzati nella libreria dell'app.
I record delle attività API e i relativi file di input, risultato e anteprima vengono conservati per 1 ora dopo il completamento, l'errore o l'annullamento dell'attività. Il campo expiresAt indica l’ora prevista per la pulizia.
Usa DELETE /v1/jobs/{job_id} dopo aver scaricato i risultati che non ti servono più. Annulla se possibile il lavoro non finito ed elimina il record del job e i file propri dell'API prima della pulizia automatica.