ID PhotoREST · JSONOpenAPI 3.1

SVOYAGER ID Photo API

Transformez n'importe quelle photo en une photo d'identité, de passeport ou de visa conforme aux normes.

Présentation générale

Fonctionnalité

L’API ID Photo API de SVOYAGER transforme un portrait ordinaire en une photo d’identité conforme. ID Photo est un produit unique : passeport, visa, titre de séjour et carte d’identité nationale sont représentés comme des spécifications de documents, et non comme des produits distincts. Vous téléchargez une photo, générez un aperçu avec filigrane selon une spécification, puis finalisez pour obtenir le résultat sans filigrane.

Aperçu → flux de travail final

  1. 1Téléchargez une photo. Créez une destination de téléchargement et envoyez-y les octets de l'image.
  2. 2Créer une session. Générez un aperçu avec filigrane par rapport à une spécification. Vérifiez les problèmes signalés.
  3. 3Finaliser. Transformez la session révisée en commande et recevez la version finale sans filigrane.

Guide de démarrage rapide

Chaque requête est authentifiée à l'aide d'une clé secrète Bearer. Commencez en mode test :

curl
# List specifications to find a spec_id
curl -G "https://partner.svoyager.com/v1/photo-specifications" \
  -H "Authorization: Bearer svoy_sk_test_YOUR_KEY" \
  --data-urlencode "country=US"

URL de base et environnements

Tous les points de terminaison sont accessibles via une seule URL de base :

Base URL
https://partner.svoyager.com/v1

Il n’y a ni chemin d’accès ni paramètre d’environnement. Le fait qu’une requête s’exécute en mode test ou en production est entièrement déterminé par le préfixe de votre clé API (svoy_sk_test_… vs svoy_sk_live_…). Les réponses reflètent cela sous la forme « livemode ».

Authentification

Clés API

Authentifiez chaque requête à l'aide d'un en-tête « Authorization » contenant votre clé secrète. Les clés sont créées et renouvelées dans le Centre des partenaires.

Header
Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx

Le préfixe désigne l’environnement : svoy_sk_test_… pour le test, svoy_sk_live_… pour la production. Une clé de test ne peut en aucun cas agir sur des données de production (et inversement) — toute incompatibilité renvoie le code d’erreur 401 « wrong_environment ».

Portées

Les clés comportent des périmètres explicites de privilèges minimaux. Une requête ne comportant pas le périmètre requis renvoie le code d'erreur 403 insufficient_scope.

PortéeAutorisations
photo.specs.readList and retrieve photo specifications.
photo.sessions.readRetrieve sessions and their previews.
photo.sessions.writeCreate uploads and photo sessions (previews).
photo.finalize.writeFinalize a session into a no-watermark order.
photo.orders.readRetrieve orders and download finals.

Sécurisation des clés

Les clés secrètes sont réservées aux communications de serveur à serveur. N’intégrez jamais une clé secrète dans le code d’un navigateur ou d’une application mobile, dans un dépôt public ou dans un bundle côté client. Si une clé est exposée, remplacez-la immédiatement dans le Centre des partenaires.

API principale

Points de terminaison

Les champs obligatoires sont signalés par un *. Les exemples utilisent des identifiants fictifs — jamais de clés réelles.

POST/v1/uploads

Upload a photo

Create a short-lived presigned upload target, then PUT the raw image bytes straight to `upload_url`. This bypasses request-body size limits (product cap 10 MB). No quota is spent.

scope photo.sessions.write
Requête
Corps (application/json)
ChampTypeDescription
content_type*stringMIME type of the image.image/jpegimage/pngimage/webpimage/heic
  • `upload_url` is single-use and expires; upload promptly and do not modify the URL.
Exemple de requête
curl
# 1) Create the upload target
curl -X POST "https://partner.svoyager.com/v1/uploads" \
  -H "Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"content_type":"image/jpeg"}'

# 2) PUT the bytes to the returned upload_url (exactly as returned)
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg
Réponse · 201
201 · application/json
{
  "object": "upload",
  "upload_url": "https://upload.svoyager.com/v1/EXAMPLE?signature=…",
  "upload_ref": "up_ref_tXk3W2b8Qe7Ra1Nc0",
  "max_bytes": 10485760,
  "expires_at": "2026-07-24T18: 20: 00Z"
}
Erreurs
StatutCodeLorsque
400missing_content_type`content_type` was not provided.
415unsupported_formatThe content type is not an accepted image format.
503temporarily_unavailableUploads are temporarily unavailable.
502upload_init_failedThe upload could not be initialised — retry shortly.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

POST/v1/photo-sessions

Create a photo session

Generate a watermarked preview from an upload against a specification. Spends one `preview` unit of your plan. Review `issues` before finalizing.

scope photo.sessions.write Clé d'idempotence obligatoire
Requête
Corps (application/json)
ChampTypeDescription
upload_ref*stringThe `upload_ref` from Upload a photo.
spec_id*stringThe `photo_specification` id (`spc_…`) to render against.
Exemple de requête
curl
curl -X POST "https://partner.svoyager.com/v1/photo-sessions" \
  -H "Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx" \
  -H "Idempotency-Key: a7f3c9e1-2b4d-4c8a-9f10-3e5d6b7a8c9d" \
  -H "Content-Type: application/json" \
  -d '{"upload_ref":"up_ref_tXk3W2b8Qe7Ra1Nc0","spec_id":"spc_9wTv2c1Kd8Qe"}'
Réponse · 201
201 · application/json
{
  "object": "photo_session",
  "id": "3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10",
  "livemode": false,
  "status": "preview_ready",
  "spec_id": "spc_9wTv2c1Kd8Qe",
  "preview_url": "https://partner.svoyager.com/v1/photo-sessions/3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10/preview",
  "watermarked": true,
  "issues": [],
  "created_at": "2026-07-24T18: 30: 00Z"
}
Erreurs
StatutCodeLorsque
400missing_idempotency_keyThe `Idempotency-Key` header is missing.
400missing_upload_ref`upload_ref` is missing.
400missing_spec_id`spec_id` is missing.
400invalid_upload_refThe referenced upload could not be read.
413file_too_largeThe uploaded file exceeds 10 MB.
415unsupported_formatThe uploaded file is not an accepted image format.
404spec_not_foundNo active specification matches `spec_id`.
402no_active_planNo active plan is assigned for this environment.
402quota_exceededIncluded preview quota for the period is exhausted.
402plan_inactiveThe plan is not active for this environment.
409idempotency_key_reuseThe key was reused with a different body.
409request_in_progressA request with this key is still processing.
422unprocessable_imageThe image could not be processed.
502provider_errorThe preview could not be generated upstream — retry shortly.
503provider_busyThe processing service is busy — retry shortly.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

GET/v1/photo-sessions/{id}

Retrieve a photo session

Fetch a session by id, including its current status, `preview_url`, and any `issues`.

scope photo.sessions.read
Requête
Paramètres de chemin
ChampTypeDescription
id*stringSession id.
Exemple de requête
curl
curl "https://partner.svoyager.com/v1/photo-sessions/3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10" \
  -H "Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx"
Réponse · 200
200 · application/json
{
  "object": "photo_session",
  "id": "3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10",
  "livemode": false,
  "status": "preview_ready",
  "spec_id": "spc_9wTv2c1Kd8Qe",
  "preview_url": "https://partner.svoyager.com/v1/photo-sessions/3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10/preview",
  "watermarked": true,
  "issues": [],
  "created_at": "2026-07-24T18: 30: 00Z"
}
Erreurs
StatutCodeLorsque
404session_not_foundNo session matches the id for this account/environment.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

GET/v1/photo-sessions/{id}/preview

Download the preview image

Stream the watermarked preview image bytes for a session (SVOYAGER-hosted; the upstream URL is never exposed). This is the resource `preview_url` points to.

scope photo.sessions.readRenvoie les octets de l'image
Requête
Paramètres de chemin
ChampTypeDescription
id*stringSession id.
  • Returns raw `image/*` bytes on success (not JSON).
Exemple de requête
curl
curl "https://partner.svoyager.com/v1/photo-sessions/3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10/preview" \
  -H "Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx" \
  --output preview.jpg
Réponse · 200

En cas de réussite, le point de terminaison transmet les octets bruts de l’image (et non du JSON). Enregistrez le corps de la réponse dans un fichier.

Erreurs
StatutCodeLorsque
404preview_not_foundThe session or its preview does not exist.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

POST/v1/photo-sessions/{id}/finalize

Finalize a photo

Turn a reviewed session into a deliverable order. In live mode this produces the no-watermark final and spends one `final` unit; in test mode it emulates the final from the preview.

scope photo.finalize.write Clé d'idempotence obligatoire
Requête
Paramètres de chemin
ChampTypeDescription
id*stringSession id to finalize.
Exemple de requête
curl
curl -X POST "https://partner.svoyager.com/v1/photo-sessions/3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10/finalize" \
  -H "Authorization: Bearer svoy_sk_live_A8m4Qz1YOURKEYHERExxxxxxx" \
  -H "Idempotency-Key: a7f3c9e1-2b4d-4c8a-9f10-3e5d6b7a8c9d"
Réponse · 201Returns 200 with the existing order if the session was already finalized (never double-charged).
201 · application/json
{
  "object": "photo_order",
  "id": "8a2d5b40-71c6-4f0e-b3a9-1e7c9d05f284",
  "livemode": true,
  "sandbox_emulated": false,
  "status": "final_ready",
  "session_id": "3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10",
  "spec_id": "spc_9wTv2c1Kd8Qe",
  "final_url": "https://partner.svoyager.com/v1/orders/8a2d5b40-71c6-4f0e-b3a9-1e7c9d05f284/final",
  "watermarked": false,
  "created_at": "2026-07-24T18: 31: 00Z"
}
Erreurs
StatutCodeLorsque
400missing_idempotency_keyThe `Idempotency-Key` header is missing.
404session_not_foundNo session matches the id for this account/environment.
422session_not_finalizableThe session is not in a finalizable state.
402no_active_planNo active plan is assigned for this environment.
402quota_exceededIncluded final quota for the period is exhausted.
402plan_inactiveThe plan is not active for this environment.
409idempotency_key_reuseThe key was reused with a different request.
409request_in_progressA request with this key is still processing.
502provider_errorThe final could not be produced upstream — retry shortly.
503provider_busyThe processing service is busy — retry shortly.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

GET/v1/orders/{id}

Retrieve an order

Fetch a finalized order by id, including its status and `final_url` once ready.

scope photo.orders.read
Requête
Paramètres de chemin
ChampTypeDescription
id*stringOrder id.
Exemple de requête
curl
curl "https://partner.svoyager.com/v1/orders/8a2d5b40-71c6-4f0e-b3a9-1e7c9d05f284" \
  -H "Authorization: Bearer svoy_sk_live_A8m4Qz1YOURKEYHERExxxxxxx"
Réponse · 200
200 · application/json
{
  "object": "photo_order",
  "id": "8a2d5b40-71c6-4f0e-b3a9-1e7c9d05f284",
  "livemode": true,
  "sandbox_emulated": false,
  "status": "final_ready",
  "session_id": "3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10",
  "spec_id": "spc_9wTv2c1Kd8Qe",
  "final_url": "https://partner.svoyager.com/v1/orders/8a2d5b40-71c6-4f0e-b3a9-1e7c9d05f284/final",
  "watermarked": false,
  "created_at": "2026-07-24T18: 31: 00Z"
}
Erreurs
StatutCodeLorsque
404order_not_foundNo order matches the id for this account/environment.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

GET/v1/orders/{id}/final

Download the final image

Stream the final image bytes for an order (SVOYAGER-hosted). In live mode this is the no-watermark deliverable; in test mode it is the sandbox-emulated copy. This is the resource `final_url` points to.

scope photo.orders.readRenvoie les octets de l'image
Requête
Paramètres de chemin
ChampTypeDescription
id*stringOrder id.
  • Returns raw `image/*` bytes on success (not JSON).
Exemple de requête
curl
curl "https://partner.svoyager.com/v1/orders/8a2d5b40-71c6-4f0e-b3a9-1e7c9d05f284/final" \
  -H "Authorization: Bearer svoy_sk_live_A8m4Qz1YOURKEYHERExxxxxxx" \
  --output final.jpg
Réponse · 200

En cas de réussite, le point de terminaison transmet les octets bruts de l’image (et non du JSON). Enregistrez le corps de la réponse dans un fichier.

Erreurs
StatutCodeLorsque
404final_not_foundThe order or its final does not exist.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

GET/v1/photo-specifications

List photo specifications

Return a cursor-paginated list of available photo specifications. Filter by country or document type to find the `spec_id` you need.

scope photo.specs.read
Requête
Paramètres de requête
ChampTypeDescription
limitintegerPage size, 1–100 (default 20).
starting_afterstringA specification id (`spc_…`) to page after.
countrystringISO-3166 alpha-2 filter, e.g. `US`.
document_typestringFilter by document type, e.g. `passport`.
Exemple de requête
curl
curl -G "https://partner.svoyager.com/v1/photo-specifications" \
  -H "Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx" \
  --data-urlencode "country=US" \
  --data-urlencode "limit=20"
Réponse · 200
200 · application/json
{
  "object": "list",
  "data": [
    {
      "object": "photo_specification",
      "id": "spc_9wTv2c1Kd8Qe",
      "name": "United States Passport"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
Erreurs

Ce point de terminaison ne renvoie que les erreurs standard ci-dessous.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

GET/v1/photo-specifications/{id}

Retrieve a photo specification

Fetch a single specification by its stable `spec_id`, including its full requirements.

scope photo.specs.read
Requête
Paramètres de chemin
ChampTypeDescription
id*stringSpecification id (`spc_…`).
Exemple de requête
curl
curl "https://partner.svoyager.com/v1/photo-specifications/spc_9wTv2c1Kd8Qe" \
  -H "Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx"
Réponse · 200
200 · application/json
{
  "object": "photo_specification",
  "id": "spc_9wTv2c1Kd8Qe",
  "name": "United States Passport",
  "country_code": "US",
  "document_type": "passport",
  "physical_size": {
    "width": 51,
    "height": 51,
    "unit": "mm"
  },
  "pixel_size": {
    "width": 600,
    "height": 600
  },
  "dpi": 300,
  "background": {
    "color": "#FFFFFF",
    "name": "white"
  },
  "requirements": {
    "head_height": "25–35 mm (1–1⅜ in)",
    "eye_to_bottom": "28–35 mm (1⅛–1⅜ in)",
    "recency_months": 6,
    "expression": "neutral",
    "color": true,
    "glasses": "not allowed",
    "eyes_and_ears": "both eyes open"
  },
  "updated_at": "2026-07-01T12: 00: 00Z"
}
Erreurs
StatutCodeLorsque
404spec_not_foundNo active specification matches the id.

Sans oublier les erreurs standard liées à l’authentification, aux autorisations et à la limitation de débit — voir Erreurs et nouvelles tentatives.

Envoyez un en-tête Idempotency-Key (une valeur unique, par exemple un UUID) afin qu’une requête réessayée ne soit jamais comptabilisée ou traitée deux fois. Il est obligatoire pour :

  • POST /v1/photo-sessions
  • POST /v1/photo-sessions/{id}/finalize
  • Même clé + même corps → le résultat d'origine est reproduit (pas de deuxième facturation, pas de deuxième rendu).
  • Même clé + un corps différent → 409 idempotency_key_reuse.
  • Une erreur réessayable vous permet de réessayer avec la même clé, le même corps et le même upload_ref.
  • Les requêtes de finalisation simultanées pour une même session ne peuvent en aucun cas créer ou facturer deux commandes.

Une session passe par différents états de prévisualisation ; une commande, par différents états de finalisation.

État de la session
  • preview_readyAperçu généré, aucun problème.
  • preview_has_issuesAperçu généré avec des problèmes.
  • preview_failedL'aperçu n'a pas pu être généré.
  • finalizedla session a été clôturée.
Statut de la commande
  • final_readyLa version finale est disponible.
  • processingLa version finale est en cours de préparation.
  • failedÉchec de la finalisation.

L'environnement est déterminé par le préfixe de votre clé — les clients ne peuvent en aucun cas le transmettre. Le mode test affiche un aperçu réel avec filigrane afin que vous puissiez tester le flux réel, mais simule le résultat final ; ainsi, aucun quota en production ni aucun rendu de production n'est utilisé.

AspectTestEn direct
livemodefalsetrue
AperçuRéel, avec filigraneRéel, avec filigrane
FinalÉmulé en mode sandbox à partir de la préversionAuthentique, sans filigrane
sandbox_emulatedtruefalse
watermarkedtruefalse
Quota consomméQuota de test uniquementQuota en production uniquement

Votre forfait comprend un certain nombre de « previews » et de « finals » par période, comptabilisés séparément. La création d’une session consomme un « preview » ; la finalisation consomme un « final ». Le quota est réservé de manière atomique avant le traitement.

  • Lorsque le quota d’aperçu ou le quota final inclus est épuisé, la requête renvoie le code d’erreur 402 « quota_exceeded ».
  • Le code 402 correspond à un blocage définitif : toute nouvelle tentative échouera jusqu’à la période suivante ou à un changement de forfait.
  • Les quotas de test et de production sont totalement indépendants.

Chaque erreur utilise une enveloppe. L’identifiant request_id apparaît également dans l’en-tête de réponse X-Request-Id — veuillez l’inclure dans vos demandes d’assistance.

Error envelope
{
  "error": {
    "type": "invalid_request_error",
    "code": "quota_exceeded",
    "message": "Your included final quota for this period is exhausted.",
    "request_id": "req_9wTv2c1Kd8QeR7"
  }
}

Erreurs standard (tous les points de terminaison)

StatutCodeLorsque
401invalid_api_keyMissing, malformed, or unknown API key.
401revoked_api_keyThe key was revoked.
401expired_api_keyThe key passed its rotation grace period.
401wrong_environmentA test key was used on live traffic (or vice versa).
403client_disabledThe API client is disabled.
403api_access_revokedAPI access for the account is not active.
403insufficient_scopeThe key lacks the required scope for this endpoint.
429rate_limitedPer-key rate limit exceeded. Honour `Retry-After`.

Le code 422 n’est renvoyé qu’en cas de problème d’image confirmé. Le code 402 indique que le quota est épuisé. Le code 409 correspond à un conflit d’idempotence ou de ressource.

Le code 429 indique que vous avez atteint la limite de débit par clé — respectez l’en-tête Retry-After. Pour les codes 502/503 et autres codes 5xx, réessayez en respectant un délai d’attente et en utilisant la même Idempotency-Key.

Un aperçu peut renvoyer zéro ou plusieurs problèmes, chacun étant constitué d’un code stable et d’un message. Affichez-les à l’utilisateur final afin qu’il puisse reprendre la photo. Un signal en amont non reconnu est reclassé en « autre ».

CodeMessage
face_not_foundNo face was detected in the photo.
uneven_lightingLighting on the face is uneven.
poor_brightnessFace brightness is too dark, too bright, or the photo is low quality.
low_sharpnessThe photo is blurry or not sharp enough.
eyeglasses_not_allowedEyeglasses are not allowed.
sunglasses_not_allowedSunglasses are not allowed.
headwear_not_allowedHats or head coverings are not allowed.
face_mask_not_allowedA face mask is not allowed.
face_covering_foundA face covering was detected.
expression_not_neutralThe expression is not neutral.
crop_bottomNot enough space is visible below the shoulders.
crop_leftNot enough of the left shoulder is visible.
crop_rightNot enough of the right shoulder is visible.
head_turnedThe head is turned too far to the side.
head_tiltedThe head is tilted too far up or down.
not_in_colorThe photo must be in color.
otherThe photo did not meet a requirement.
  • Les aperçus et les versions finales ne sont accessibles qu’à partir d’URL authentifiées hébergées par SVOYAGER. L’accès nécessite votre clé API et la portée appropriée — le stockage sous-jacent n’est jamais exposé publiquement.
  • Les images téléchargées sont privées et limitées à votre compte et à votre environnement ; les cibles de téléchargement ont une durée de vie limitée et sont à usage unique.
  • Les photos des documents sont traitées pour générer votre résultat et ne sont pas partagées entre les comptes.

Consultez les conditions de SVOYAGER relatives au traitement, à la conservation et à la suppression des données :Politique de confidentialité ·Contrat de partenariat et conditions générales