Linq protocol (as observed)

Based on linq-sim (~/code/cortex/cloudcli/dev-tools/linq-sim/) and Cortex's backend/src/routes/sms.ts normalization layer. This is our ground truth until Jacob gets real Linq partner docs.

Inbound webhook

POST $OUR_BASE/api/linq/inbound

Headers

  • Content-Type: application/json
  • Linq-Signature: t=<unix_ts>,s=<hex_hmac_sha256>
  • Linq-Event-Id: <uuid> (dedup key)

Body shape (union of all events)

{
  "type": "message.received",
  "id": "evt_...",
  "timestamp": 1714065000,
  "chat_id": "chat_abc",
  "data": {
    "message_id": "msg_...",
    "sender": { "phone": "+15551234567", "name": "..." },
    "text": "...",
    "reply_to_message_id": "msg_parent",   // NEW — requires S2 sim PR
    "attachments": []
  }
}

Supported event types

message.received
message.delivered
message.read
message.edited
message.failed
reaction.added
reaction.removed
chat.typing_indicator.started
chat.typing_indicator.stopped
chat.created
chat.updated
chat.group_name_updated
participant.added
participant.removed

HMAC verification

signed_payload = f"{timestamp}.{raw_body_bytes}"
expected_sig   = hmac_sha256(signed_payload, secret)

Constant-time compare expected_sig vs s= value.

Reject if:

  • Signature header missing / malformed → 401
  • expected_sig mismatch → 401
  • now - timestamp > 300 → 401 (skew)
  • Linq-Event-Id seen in last 24h → 200 (dedup no-op)

Outbound partner API

$LINQ_BASE_URL/api/partner/v3/...

  • POST /sendMessage{ chat_id, text, reply_to_message_id?, attachments? }
  • POST /createChat{ participants: [phone, ...] }
  • GET /getChat?chat_id=...
  • POST /addParticipant / removeParticipant / updateChat

Auth: Authorization: Bearer $LINQ_API_KEY (assumed — confirm with real Linq docs).

Reactions

Set: {heart, thumbs_up, thumbs_down, laugh, exclaim, question} (iMessage's native tapbacks). target_message_id required on reaction.added. linq-sim enforces 400 when missing.

Threads / replies

iMessage has inline replies (reply_to_message_id). linq-sim does NOT currently implement this; S2 adds it. picortex requires it before S7 mobile UI can render reply pills properly.

Things we don't know yet

  • Rate limits on outbound sendMessage
  • Attachment size caps
  • Whether Linq preserves read receipts across edits
  • Whether chat.created fires for a 1:1 on first message or only on explicit creation
[[curator]]
I'm the Curator. I can help you navigate, organize, and curate this wiki. What would you like to do?