ID PhotoREST · JSONOpenAPI 3.1

SVOYAGER ID Photo API

将任何照片转换为符合规范的身份证/护照/签证照片。

概述

功能说明

SVOYAGER 的 ID Photo API 可将普通人像照片转换为符合规范的证件照。ID Photo 是一个单一产品:护照、签证、居留许可和国民身份证均作为证件规范呈现,而非独立产品。 您上传照片,根据规范生成带水印的预览,然后进行最终处理以获得无水印的结果。

预览 → 最终工作流

  1. 1上传照片. 创建一个上传目标,并将图像字节发送至该目标。
  2. 2创建会话. 根据规范渲染带水印的预览图。审查返回的问题。
  3. 3最终定稿. 将审核后的会话转换为订单,并获取无水印的最终版本。

快速入门

每个请求均使用 Bearer 密钥进行身份验证。请从测试模式开始:

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 和环境

所有端点均通过单一基础 URL 提供服务:

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

不存在环境路径或参数。请求是在测试环境还是生产环境中运行,完全由您的 API 密钥前缀决定(svoy_sk_test_… 与 svoy_sk_live_…)。响应中会将此信息作为 livemode 返回。

身份验证

API密钥

请通过携带您的密钥的 Authorization 头对每个请求进行身份验证。密钥在“合作伙伴中心”中创建和轮换。

Header
Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx

前缀用于标识环境:svoy_sk_test_… 表示测试环境,svoy_sk_live_… 表示生产环境。测试密钥绝不能对生产数据进行操作(反之亦然)——若环境不匹配,将返回 401 wrong_environment 状态码。

作用域

密钥携带明确的最小权限范围。如果请求缺少所需的范围,将返回 403 insufficient_scope 状态码。

范围授权
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.

确保密钥安全

密钥仅限服务器间使用。切勿将密钥嵌入浏览器或移动端代码、公共代码库或客户端打包文件中。若密钥泄露,请立即在“合作伙伴中心”中轮换密钥。

核心 API

端点

必填字段标有 *。示例中使用的是占位凭据——绝非真实密钥。

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
请求
正文 (application/json)
字段类型描述
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.
请求示例
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
响应 · 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"
}
错误
状态代码
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.

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

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 必须包含幂等性密钥
请求
正文 (application/json)
字段类型描述
upload_ref*stringThe `upload_ref` from Upload a photo.
spec_id*stringThe `photo_specification` id (`spc_…`) to render against.
请求示例
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"}'
响应 · 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"
}
错误
状态代码
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.

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

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
请求
路径参数
字段类型描述
id*stringSession id.
请求示例
curl
curl "https://partner.svoyager.com/v1/photo-sessions/3f9c1e77-2b8a-4a1e-9d2c-6b5a4c3d2e10" \
  -H "Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx"
响应 · 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"
}
错误
状态代码
404session_not_foundNo session matches the id for this account/environment.

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

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.read返回图像字节
请求
路径参数
字段类型描述
id*stringSession id.
  • Returns raw `image/*` bytes on success (not JSON).
请求示例
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
响应 · 200

成功时,该端点将流式传输原始图像字节(而非 JSON)。将响应正文保存到文件中。

错误
状态代码
404preview_not_foundThe session or its preview does not exist.

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

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 必须包含幂等性密钥
请求
路径参数
字段类型描述
id*stringSession id to finalize.
请求示例
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"
响应 · 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"
}
错误
状态代码
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.

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

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
请求
路径参数
字段类型描述
id*stringOrder id.
请求示例
curl
curl "https://partner.svoyager.com/v1/orders/8a2d5b40-71c6-4f0e-b3a9-1e7c9d05f284" \
  -H "Authorization: Bearer svoy_sk_live_A8m4Qz1YOURKEYHERExxxxxxx"
响应 · 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"
}
错误
状态代码
404order_not_foundNo order matches the id for this account/environment.

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

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.read返回图像字节
请求
路径参数
字段类型描述
id*stringOrder id.
  • Returns raw `image/*` bytes on success (not JSON).
请求示例
curl
curl "https://partner.svoyager.com/v1/orders/8a2d5b40-71c6-4f0e-b3a9-1e7c9d05f284/final" \
  -H "Authorization: Bearer svoy_sk_live_A8m4Qz1YOURKEYHERExxxxxxx" \
  --output final.jpg
响应 · 200

成功时,该端点将流式传输原始图像字节(而非 JSON)。将响应正文保存到文件中。

错误
状态代码
404final_not_foundThe order or its final does not exist.

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

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
请求
查询参数
字段类型描述
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`.
请求示例
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"
响应 · 200
200 · application/json
{
  "object": "list",
  "data": [
    {
      "object": "photo_specification",
      "id": "spc_9wTv2c1Kd8Qe",
      "name": "United States Passport"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
错误

该端点仅返回以下标准错误。

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

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
请求
路径参数
字段类型描述
id*stringSpecification id (`spc_…`).
请求示例
curl
curl "https://partner.svoyager.com/v1/photo-specifications/spc_9wTv2c1Kd8Qe" \
  -H "Authorization: Bearer svoy_sk_test_R2p9Kx7YOURKEYHERExxxxxxx"
响应 · 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"
}
错误
状态代码
404spec_not_foundNo active specification matches the id.

此外还包括标准的身份验证、权限和速率限制错误——参见 错误与重试.

请发送 Idempotency-Key 头(一个唯一值,例如 UUID),以确保重试请求绝不会产生重复计费或重复处理。以下情况必须包含该头:

  • POST /v1/photo-sessions
  • POST /v1/photo-sessions/{id}/finalize
  • 相同密钥 + 相同请求体 → 重放原始结果(不产生二次请求,不进行二次渲染)。
  • 相同密钥 + 不同请求体 → 409 idempotency_key_reuse。
  • 可重试的错误允许您使用相同的密钥、请求体和 upload_ref 进行重试。
  • 同一会话中并发处理的最终确认请求绝不会创建或计费两笔订单。

会话会经历预览状态;订单则会经历最终确认状态。

会话状态
  • preview_ready已生成预览,无问题。
  • preview_has_issues预览内容包含已知问题。
  • preview_failed无法生成预览。
  • finalized会话已结束。
订单状态
  • final_ready最终版本已发布。
  • processing最终版本正在准备中。
  • failed最终化失败。

环境由您的密钥前缀决定——客户端绝不能传递该前缀。测试模式会运行带有水印的真实预览,以便您体验真实的流程,但会模拟最终效果,因此不会使用实时配额或生产环境渲染。

Aspect测试实时
livemodefalsetrue
预览真实,带水印真实,带水印
最终沙盒环境基于预览版模拟真实图片,无水印
sandbox_emulatedtruefalse
watermarkedtruefalse
已消耗的配额仅限测试配额仅限实时配额

您的套餐包含每个周期内的预览次数和最终版本次数,两者分别计算。创建会话将消耗一次预览配额;最终确定将消耗一次最终版本配额。配额将在处理前以原子操作方式预留。

  • 当包含的预览配额或最终配额用尽时,请求将返回 402 quota_exceeded 状态码。
  • 402 表示硬性阻塞——在下一周期开始或更改套餐之前,重试均不会成功。
  • 测试配额和生产配额完全独立。

每个错误使用一个信封。request_id 也会出现在 X-Request-Id 响应头中——请在提交支持请求时包含该值。

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

标准错误(所有端点)

状态代码
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`.

仅在确认存在图像问题时才会返回 422。402 表示配额已用尽。409 表示幂等性或资源冲突。

429 表示您已达到单密钥的速率限制——请遵守 Retry-After 标头。对于 502/503 及其他 5xx 状态码,请采用退避策略并使用相同的 Idempotency-Key 进行重试。

预览可能返回零个或多个问题,每个问题包含一个稳定代码和一条消息。将这些问题呈现给最终用户,以便他们可以重新拍摄照片。未识别的上游信号将降级为“其他”。

代码消息
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.
  • 预览版和最终版仅通过 SVOYAGER 托管的、经过身份验证的 URL 提供。访问时需要您的 API 密钥和正确的权限范围——底层存储绝不会公开暴露。
  • 上传的图片为私有,仅限于您的账户和环境;上传目标为短效且仅限一次性使用。
  • 文档照片经处理后生成您的结果,且不会在不同账户间共享。

请参阅 SVOYAGER 的数据处理、保留和删除条款:隐私政策 ·合作伙伴协议与条款