FaceSign
Reference

Webhook Events

All FaceSign webhook event types with payload schemas and delivery behavior.

This reference documents every webhook event FaceSign sends, including payload schemas, delivery timing, and retry behavior.

Common payload structure

Every webhook event includes these fields:

FieldTypeDescription
idstringUnique event identifier. Use this for idempotency.
typestringThe event type (e.g., "session.status").
createdAtnumberUnix timestamp in milliseconds when the event was created.
sessionIdstringThe session this event belongs to.
mediaobject | undefinedPresent only on media.* events. Contains the media file details.

Media object

Events with a media field include:

FieldTypeDescription
idstringUnique media identifier.
createdAtnumberUnix timestamp (ms) when the media was generated.
urlstringSigned download URL for the media file.
expiresnumberUnix timestamp (ms) when the URL expires.
contentTypestringMIME type (e.g., "image/jpeg", "video/mp4").

Event types

session.status

Fires whenever a session's status changes. You receive this event for every transition in the lifecycle: created, inProgress, incomplete, and complete.

When it fires: On every status change.

Payload:

{
  "id": "evt_12345",
  "type": "session.status",
  "createdAt": 1761594651878,
  "sessionId": "3f0a4e1e-9c2b-4b6f-8d3a-2a8e1b7c4f01"
}

media.user_photo

Fires when a user's selfie or face capture photo is ready for download.

When it fires: After a face capture completes during the session.

Payload:

{
  "id": "evt_uphoto789",
  "type": "media.user_photo",
  "createdAt": 1761595700000,
  "sessionId": "3f0a4e1e-9c2b-4b6f-8d3a-2a8e1b7c4f01",
  "media": {
    "id": "m_uphoto1",
    "createdAt": 1761595700000,
    "url": "https://media.facesign.ai/m_uphoto1.jpg",
    "expires": 1761596600000,
    "contentType": "image/jpeg"
  }
}

media.document_photo

Fires when a scanned document photo is ready for download.

When it fires: After the user completes a document scan node.

Payload:

{
  "id": "evt_udoc456",
  "type": "media.document_photo",
  "createdAt": 1761595720000,
  "sessionId": "3f0a4e1e-9c2b-4b6f-8d3a-2a8e1b7c4f01",
  "media": {
    "id": "m_udoc2",
    "createdAt": 1761595720000,
    "url": "https://media.facesign.ai/m_udoc2.jpg",
    "expires": 1761596620000,
    "contentType": "image/jpeg"
  }
}

media.user_video

Fires when the full session recording video is processed and ready for download.

When it fires: After the session ends and the video has been prepared.

Payload:

{
  "id": "evt_uvideo234",
  "type": "media.user_video",
  "createdAt": 1761595800000,
  "sessionId": "3f0a4e1e-9c2b-4b6f-8d3a-2a8e1b7c4f01",
  "media": {
    "id": "m_uvideo5",
    "createdAt": 1761595800000,
    "url": "https://media.facesign.ai/m_uvideo5.mp4",
    "expires": 1761596700000,
    "contentType": "video/mp4"
  }
}

analysis.video

Fires when post-session video AI analysis completes. This event only fires for sessions with videoAIAnalysisEnabled: true.

When it fires: 5--20 seconds after the session ends.

Payload:

{
  "id": "evt_videoanal1",
  "type": "analysis.video",
  "createdAt": 1761595900000,
  "sessionId": "3f0a4e1e-9c2b-4b6f-8d3a-2a8e1b7c4f01"
}

analysis.screenshot

Fires when screenshot-based AI analysis completes.

When it fires: Shortly after the session ends, once screenshot analysis has been processed.

Payload:

{
  "id": "evt_screenshot2",
  "type": "analysis.screenshot",
  "createdAt": 1761595910000,
  "sessionId": "3f0a4e1e-9c2b-4b6f-8d3a-2a8e1b7c4f01"
}

settings.avatars

Fires when the list of available avatars changes on the FaceSign platform. This is a platform-level event, not tied to a specific session.

When it fires: When avatars are added, removed, or updated.

Payload:

{
  "id": "evt_avtchg1",
  "type": "settings.avatars",
  "createdAt": 1761596000000,
  "sessionId": ""
}

settings.langs

Fires when the list of available languages changes on the FaceSign platform.

When it fires: When supported languages are added or removed.

Payload:

{
  "id": "evt_langs3",
  "type": "settings.langs",
  "createdAt": 1761596100000,
  "sessionId": ""
}

Event summary

EventHas media?Timing
session.statusNoOn every status transition
media.user_photoYesAfter face capture
media.document_photoYesAfter document scan
media.user_videoYesAfter session ends and video is processed
analysis.videoNo5--20s after session ends
analysis.screenshotNoShortly after session ends
settings.avatarsNoOn platform avatar changes
settings.langsNoOn platform language changes

Retry behavior

FaceSign retries failed webhook deliveries using exponential backoff:

RetryDelay
1st1 minute
2nd5 minutes
3rd15 minutes
4th1 hour
5th6 hours

Response handling:

  • HTTP 200 -- Event acknowledged. No retry.
  • HTTP 4xx -- Client error. FaceSign does not retry (the payload is considered invalid by your endpoint).
  • HTTP 5xx -- Server error. FaceSign retries according to the schedule above.

After all retries are exhausted, the event is dropped. Monitor your endpoint health to avoid missing events.

Idempotency

Webhooks may be delivered more than once. Every event has a unique id field. Use this id to deduplicate events in your handler:

  1. Before processing, check whether you have already handled an event with this id.
  2. If yes, return 200 immediately and skip processing.
  3. If no, process the event and record the id as handled.

Store processed event IDs in a persistent store (database, Redis) rather than in-memory, so deduplication survives application restarts.

export async function POST(req) {
  const event = await req.json()

  // Check for duplicate delivery
  const alreadyProcessed = await db.webhookEvents.exists(event.id)
  if (alreadyProcessed) {
    return Response.json({ received: true })
  }

  // Process the event
  await handleEvent(event)

  // Record the event ID
  await db.webhookEvents.insert({ id: event.id, processedAt: Date.now() })

  return Response.json({ received: true })
}

Next steps

On this page