Skip to main content
Before you start: complete the two-phone quickstart, choose your durable outbox and define how a receiving device is authorized. This guide defines the application contract; it is not a standalone app. A handoff is complete when the receiving application has accepted responsibility for the work. Build that decision on top of encrypted SDK messaging. Keep one protocol instance running and reuse the discovered peer address.

Define your record

Use an application-generated operation ID that survives retries and restarts. The following is an example application schema, not an SDK envelope:
Store the record in your application’s durable outbox before sending it. Save the SDK message ID alongside the operation ID for diagnostics; retries of the business operation keep the same operation ID even if they create new SDK messages.

Receive and accept

On message_received, the receiving application:
  1. Checks the sender address against its enrolled users or devices.
  2. Parses the schema and validates the requested action.
  3. Looks up the operation ID to detect a replay of work it already accepted.
  4. Commits the operation and acceptance result in one local transaction.
  5. Sends an application receipt to the sender using sendMessage.
A receipt can contain operationId, status, acceptedAt and the receiving application’s record ID. Send it over the encrypted messaging path. If the same operation arrives again, return the stored result rather than executing it again. Do not send an acceptance receipt before the local commit succeeds. If a person must approve the handoff, record and acknowledge acceptance after that decision.

Track distinct states

Test the handoff

Cut internet access while retaining the peer link. Complete a handoff and check both local records. Then disconnect the peer link, create another operation, restart the sender and reconnect. Confirm that pending work survives, each operation is applied once, and repeated receipts do not create extra work. Restore the backend path and reconcile the records through a destination adapter. Preserve the local acceptance history; backend rejection must remain visible rather than silently rewriting it.

Completion check

Done when: both devices retain the same operation ID and acceptance result through a restart, and duplicate delivery does not repeat the work. Continue with backend delivery.