Webhook

Function that delivers the analyzed results to your desired callback URL. If you register a callback_url when creating a session (performed automatically by the SDK), the analysis results are delivered in the following format.

📘

Recommendations for safe processing (idempotency and order guarantee)

Due to network delays or retries, an already-processed webhook request may be delivered again, or events may arrive out of order. To ensure the data consistency of your system, please implement idempotency and order verification logic for events according to the guide below.

1. Preventing duplicate processing (setting an idempotency key per event)

The unique key used to safely handle duplicate webhook deliveries differs by event type.

  • SESSION_COMPLETE
    • An event that occurs only once per session, when the sleep session ends.
    • Unique key combination: session_id + event
  • INFERENCE_COMPLETE (real-time sleep analysis completion event)
    • An event that occurs repeatedly within a session whenever the AI model's sleep prediction results are updated. Therefore, to guarantee the uniqueness of the event, the sequence number must also be managed together.
    • Unique key combination: session_id + event + inference_seq_num

2. Guaranteeing event order (Order Guarantee)

Depending on network conditions, a subsequent event may arrive before a preceding one. In particular, since order matters for INFERENCE_COMPLETE events, you must verify the order of events based on the inference_seq_num value in the received payload.

Retry Policy

A webhook request is considered successful when the receiving server returns a 2xx status code. Asleep automatically retries in the following cases.

  • The response status code is 408, 429, or 5xx
  • The network connection is lost or a timeout occurs

Retries are performed up to 15 times, after which the webhook delivery is treated as a final failure. The retry intervals follow the sequence below.

(10, 10, 30, 10, 10, 480, 10, 10, 2430, 10, 10, 7680, 10, 10) 

Request

Method

POST

Header

FieldTypeDescription
x-api-keyStringAPI key used to upload data or end session
x-user-idStringThe user id that created the sleep session
X-Asleep-TimestampStringTime the webhook was sent (Unix timestamp, seconds) - included only when a webhook secret has been issued
X-Asleep-SignatureStringHMAC-SHA256 signature. Included only when a webhook secret has been issued. See Verifying Webhook HMAC Signatures for more details

Body

FieldTypeDescription
eventString (INFERENCE_COMPLETE,SESSION_COMPLETE)Webhook event type
INFERENCE_COMPLETE: If the analysis is completed within 5 or 40 minute increments
SESSION_COMPLETE: The entire session analysis is complete
versionString
(V1,V2,V3)
Webhook version
V1: Follows the webhook format of the v1.0 documentation
V2: Follows the webhook format of the v2.0 documentation
V3: Follows the webhook format of the current version
dataWebhook Data ObjectWebhook data

Webhook Data Object in case of INFERENCE_COMPLETE

FieldTypeDescription
user_idStringuser id
session_idStringsession id
seq_numIntOrder number of the audio data uploaded
inference_seq_numIntNumber that converted seq_num into 5 minutes increments
e.g.) when uploading MELSPECTROGRAM, if seq_num 39, inference_seq_num is 3
stage_list[Int]Sleep stage results in the previous 5-minute frame. You receive the most recently analyzed stride/30 values (e.g., stride 300s = 10 values, 1200s = 40 values, 2400s = 80 values)
snoring_stages[Int]Snoring stage results in the previous 5-minute frame. You receive the most recently analyzed stride/30 values (e.g., stride 300s = 10 values, 1200s = 40 values, 2400s = 80 values)

{
    "event": "INFERENCE_COMPLETE",
    "version": "V3",
    "data": {
        "user_id": "G-20250115025029-vLErWBfQNtnfvgDccFOQ",
        "session_id": "20250115025029_fvivn",
        "seq_num": 39,
        "inference_seq_num": 3,
        "sleep_stages": [0], // omitted
        "breath_stages": null,
        "snoring_stages": [0] // omitted
    }
}

Webhook Data Object in case of SESSION_COMPLETE

FieldTypeDescription
dataSleep Data ObjectThe response format is the same as Get Session in the Data API, with the only difference being the addition of user_id.

{
    "event": "SESSION_COMPLETE",
    "version": "V3",
    "data": {
        "timezone": "UTC",
        "peculiarities": ["NO_BREATHING_STABILITY"],
        "missing_data_ratio": 0.0,
        "user_id": "G-20250115025029-vLErWBfQNtnfvgDccFOQ",
        "session": {
            "id": "20250115025029_fvivn",
            "state": "COMPLETE",
            "start_time": "2025-01-15T02:50:29+00:00",
            "end_time": "2025-01-15T03:50:29+00:00",
            "unexpected_end_time": null,
            "created_timezone": "UTC",
            "sleep_stages": [0], // omitted
            "breath_stages": null, 
            "snoring_stages": [0] // omitted
        },
        "stat": {
            "sleep_time": "2025-01-15T03:05:29+00:00",
            "wake_time": "2025-01-15T03:26:29+00:00",
            "sleep_index": 50,
            "sleep_latency": 900,
            "wakeup_latency": 1440,
            "light_latency": 0,
            "deep_latency": null,
            "rem_latency": null,
            "time_in_bed": 3600,
            "time_in_sleep_period": 1260,
            "time_in_sleep": 1080,
            "time_in_wake": 180,
            "time_in_light": 1080,
            "time_in_deep": 0,
            "time_in_rem": 0,
            "time_in_stable_breath": null,
            "time_in_unstable_breath": null,
            "time_in_snoring": 0,
            "time_in_no_snoring": 1260,
            "sleep_efficiency": 0.3,
            "sleep_ratio": 0.86,
            "wake_ratio": 0.14,
            "light_ratio": 0.86,
            "deep_ratio": 0.0,
            "rem_ratio": 0.0,
            "stable_breath_ratio": null,
            "unstable_breath_ratio": null,
            "snoring_ratio": 0.0,
            "no_snoring_ratio": 1.0,
            "breathing_index": null,
            "breathing_pattern": null,
            "waso_count": 1,
            "longest_waso": 180,
            "sleep_cycle_count": 0,
            "sleep_cycle": null,
            "sleep_cycle_time": [],
            "unstable_breath_count": null,
            "snoring_count": 0
        }
    }
}

Did this page help you?