[[
wikihub
]]
Search
⌘K
Explore
People
For Agents
Sign in
Explore
People
For Agents
Sign in
@jacobcole / picortex — planning / docs/wiki/linq-protocol.md
Suggest edit
Cancel
Submit suggestion
Title
Name
Note
--- visibility: public --- # 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) ```json { "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](../plans/2026-04-23-initial-roadmap.md#s2-linq-sim-thread-support) 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 ## Related - [Spec 006 — Linq integration](../specs/006-linq-integration.md) - [ADR-0004 — Linq as primary channel](../adrs/0004-linq-primary-channel.md) - Cortex: `~/code/cortex/docs/future-plans/2026-03-31-linq-channel-plugin.md`