Skip to main content

Overview

The sync process retrieves stored data from the Whoop 4.0 device. The workflow involves requesting batch information, triggering data retrieval, and receiving large 96-byte data packets containing physiological measurements.

Sync Workflow

1

Connect to Device

Establish BLE connection to the device. The device will automatically send notifications on DATA_FROM_STRAP containing current status information.
2

Receive Batch Information

The last notification received on DATA_FROM_STRAP contains the batch number needed to request stored data.Packet format:
FieldBytesExampleDescription
Header5aa1c00ab31Packet header
Packet Count118Sequential counter
Category102Packet type identifier
Unix Time4f65c7066Timestamp (little-endian)
Status Data6804043000000Device status information
Batch Number42e470100Critical: needed for retrieval
Padding404000000Zero padding
Reserved400000000Reserved bytes
Checksum47f873cf3CRC-32 checksum
Real examples:
aa1c00ab31 18 02 f65c7066 804043000000 2e470100 04000000000000 7f873cf3
aa1c00ab31 19 02 fb5c7066 704143000000 2e470100 04000000000000 f277ceb0
aa1c00ab31 1a 02 005d7066 684243000000 2e470100 04000000000000 6b7b573f
aa1c00ab31 1b 02 055d7066 684343000000 2e470100 04000000000000 0b876f87
3

Request Batch Data

Send a command to CMD_TO_STRAP with the extracted batch number to trigger data retrieval.Command format:
aa10005723{packet_count}1701{batch_number}00000000{checksum}
Where:
  • aa10005723 = Command header
  • {packet_count} = 1 byte sequential counter
  • 1701 = Batch retrieval command code
  • {batch_number} = 4 bytes from step 2
  • 00000000 = Padding
  • {checksum} = CRC-32 checksum
4

Receive Data Packets

After sending the batch request, the device sends a burst of 96-byte data packets on DATA_FROM_STRAP. Each packet contains detailed physiological measurements.See Data Retrieval for packet structure details.
5

Enable Device Features

After data retrieval completes, two enable commands are sent:
aa0800a823 15 73 01 f4a43bfa  # Enable command 0x73
aa0800a823 16 74 01 6a8c3cb7  # Enable command 0x74
These commands return notifications on CMD_FROM_STRAP with value 01.

Batch Number Extraction

The batch number is critical for data retrieval. Extract it from the status packet: Example packet:
aa1c00ab31 18 02 f65c7066 804043000000 2e470100 04000000000000 7f873cf3
                                       ^^^^^^^^
                                       Batch number (little-endian)
Extract bytes 17-20 (4 bytes):
  • Position: After header (5) + counter (1) + category (1) + unix (4) + status (6) = 17 bytes
  • Length: 4 bytes
  • Example value: 2e470100 = batch number 83,758

Implementation Example

import struct

def extract_batch_number(packet_hex):
    """Extract batch number from status packet"""
    packet = bytearray.fromhex(packet_hex)
    # Batch number at bytes 17-20 (little-endian u32)
    batch_num = struct.unpack('<I', packet[17:21])[0]
    return batch_num

def create_batch_request(batch_number, packet_count):
    """Create batch retrieval command"""
    # Command format: aa10005723{count}1701{batch}00000000{checksum}
    header = bytearray.fromhex('aa10005723')
    count = bytes([packet_count])
    cmd_code = bytearray.fromhex('1701')
    batch = struct.pack('<I', batch_number)
    padding = bytearray.fromhex('00000000')
    
    # Assemble command (without checksum)
    cmd = header + count + cmd_code + batch + padding
    
    # Calculate CRC-32 checksum (see Commands section)
    checksum = calculate_crc32(cmd)
    
    return cmd + checksum

# Example usage
status_packet = "aa1c00ab3118 02 f65c7066 804043000000 2e470100 04000000000000 7f873cf3"
batch_num = extract_batch_number(status_packet.replace(' ', ''))
print(f"Batch number: {batch_num}")  # Output: 83758

# Create retrieval command
cmd = create_batch_request(batch_num, packet_count=0x42)
print(f"Command: {cmd.hex()}")

Sync Behavior Notes

  • The app requests journal data before and after sync operations
  • If sync fails initially, the app will retry after requesting the journal again
  • Sync can be triggered by opening the app after extended Bluetooth disconnection
  • The device buffers data locally and sends it in batches during sync
CommandCategoryDescription
0x16Data syncTriggers data retrieval on DATA_FROM_STRAP
0x23SyncSent during sync process
0x73EnablePost-sync enable command
0x74EnablePost-sync enable command (may return string data)
The sync process is also triggered when the alarm is tapped on the device. The 0x16 command initiates data retrieval in this scenario as well.

Build docs developers (and LLMs) love