Plattform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Modelle Tools & Services
Lösungen
Organisationen Entwickler Internet Service Provider Managed Service Provider AI-in-a-Box
Ressourcen
Support Documentation Blog Downloads
Unternehmen
Über uns Forschung Karriere Investieren Kontakt
Anmelden

SCWP wire reference

SCWP — ScaiClip Wire Protocol — is a binary protocol over WebSocket. All client-originated messages are dispatched by an 8-bit type code. Bodies are canonical CBOR (RFC 8949 §4.2.1).

Endpoint. wss://scaigrid.scailabs.ai/v1/modules/scaiclip/ws. Sub-protocol scaiclip/1. Auth via ?token=<sgk_> query param or Authorization: Bearer <jwt> header.

Frame format. 16-byte header (little-endian) + CBOR body. See §2 of the wire spec for the layout. Every request carries a monotone request_id; the response echoes it. Grid-originated pushes use the high half (0x8000_0000+).

Client → grid verbs#

Channel verbs#

Type Verb Body Response
0x01 channel.list {} {1: [ChannelInfo], ...}
0x02 channel.subscribe {1: [channel_id]} {1: [channel_id]}
0x03 channel.unsubscribe {1: [channel_id]} {1: [channel_id]}
0x04 channel.sync {1: channel_id, 2: from_seq, 3: limit} {1: [Envelope], 2: {seq: ciphertext}, 3: head_seq, 4: [tombstoned_seq]}
0x05 channel.create {1: kind, 2: name, 3: group, 4: peer, 5: policy_overrides, 6: initial_wraps} {1: channel_id, 2: 1}
0x06 channel.devices {1: channel_id} {1: [{1: device_id, 2: subject, 3: kem_pub, 4: sig_pub, 5: online}]}

ChannelInfo is {1: channel_id_bytes, 2: kind_enum, 4: perms_bitfield, 5: key_version, 6: {1: ttl_default_s, 2: ttl_max_s, 3: history_depth}}.

Clip verbs#

Type Verb Body Response
0x10 clip.publish {1: Envelope, 2: ciphertext, 3: [WrapRecord]} (wraps required iff ONE_SHOT) {1: seq, 2: grid_ts, 3: ttl_effective_s, 4: replayed}
0x11 clip.fetch {1: channel_id, 2: seq} or {3: clip_id} {1: Envelope, 2: ciphertext}
0x12 clip.pin {1: channel_id, 2: seq} {}
0x13 clip.unpin {1: channel_id, 2: seq} {}
0x14 clip.delete {1: channel_id, 2: seq} {}
0x15 clip.claim {1: channel_id, 2: seq} {1: WrapRecord, 2: ciphertext}

Key wrap verbs#

Type Verb Body Response
0x20 key.wraps.get {1: channel_id, 2: key_version} {1: WrapRecord} or E_NOT_FOUND
0x21 key.wraps.put {1: channel_id, 2: key_version, 3: [WrapRecord]} {}
0x22 key.rekey.complete {1: channel_id, 2: new_key_version} {}

WrapRecord = {1: device_id, 2: hpke_enc (32 bytes), 3: wrap_blob, 4: key_version}.

Presence#

Type Verb Body Response
0x30 presence.devices {} {1: [{1: device_id, 2: online, 3: last_seen}]}

Scratch storage#

Type Verb Body Response
0x40 scratch.reserve {1: size, 2: sha256_hex, 3: mime_hint, 4: sharing_mode, 5: intended_ttl_s} {1: object_id, 2: upload_url, 4: expires_at_ms, 5: quota_warning?}
0x41 scratch.commit {1: object_id, 2: sha256_hex, 3: [WrapRecord]} {1: object_id, 2: committed_at_ms, 3: expires_at_ms}
0x42 scratch.get {1: object_id} {1: object_id, 2: download_url, 3: size, 4: sha256_hex}
0x43 scratch.list {1: cursor?, 2: limit?} {1: [{1: object_id, 2: size, 3: mime, 4: sharing_mode, 5: created_at_ms, 6: expires_at_ms}]}
0x44 scratch.delete {1: object_id} {1: object_id, 2: deleted_at_ms}
0x45 scratch.publish {1: object_id, 2: expires_at_ms, 3: download_limit, 4: password_bound} {1: token, 2: public_url, 3: revoke_token, 4: expires_at_ms}

Media proxy (ref_origin)#

Type Verb Body Response
0x50 media.fetch {1: channel_id, 2: seq} {1: MediaRef, 2: transfer_id} or E_ORIGIN_OFFLINE
0x52 media.pull_stream {1: transfer_id, 2: chunk_index, 3: chunk_bytes, 4: is_final} (origin → grid) {1: "ok", 2: chunk_index, 3: is_final}
0x53 media.pull_range `{1: transfer_id sha256_hex, 2: chunk_index}`
0x54 media.cancel {1: transfer_id} {1: "cancelled"}

SCSG (user-side)#

Type Verb Body Response
0x62 session.deny {1: grant_id, 2: reason} {1: "denied"}

Grid → client push events#

Type Event Body
0x80 ok (response body per verb)
0x81 error {1: code, 2: wire_name, 3: message, 4: detail} — see error codes
0x90 clip.new {1: Envelope, 2: ciphertext?} (inline for small clips)
0x91 clip.expired {1: channel_id, 2: seq, 3: reason}
0x92 clip.claimed {1: channel_id, 2: seq, 3: claimant_subject, 4: claimant_device_id, 5: at_ms}
0x93 clip.deleted {1: channel_id, 2: seq}
0x94 rekey.required {1: channel_id, 2: new_key_version, 3: reason}
0x95 channel.membership {1: channel_id, 2: added_devices?, 3: removed_devices?}
0x96 wrap.request {1: channel_id, 2: requester_device_id, 3: requester_subject, 4: requester_kem_pub, 5: key_version}
0x97 wraps.ready {1: channel_id, 2: target_device_id, 3: key_version}
0xA0 session.grant_request {1: grant_id, 2: service_id, 3: reason, 4: {1: channel_ids, 2: capabilities}, 5: duration_max_s, 6: ephemeral_sig_pub, 7: consent_deadline_ms, 8: service_display_name}
0xB0 presence.device_state {1: device_id, 2: online, 3: at_ms}

Envelope key registry#

Key Meaning Notes
1 clip_id UUIDv7 (client-generated)
2 channel_id bytes(16)
3 seq grid-assigned
4 sender text (usr_alice)
5 device_id bytes(16) or text (nanoid)
6 client_ts ms
7 grid_ts ms, grid-assigned
8 type_hint 0-4
9 size_class 0 inline · 1 reference
10 cflags bit0 SENSITIVE · bit1 ONE_SHOT · bit2 PINNED
11 ttl_s client-requested, grid-clamps
12 key_version channel key at publish time
13 source_app optional identifier ("mobile", "browser", …)
14 payload_hash SHA-256 of ciphertext
15 sig Ed25519 over canonical CBOR of keys 1-14
20 payload_ref MediaRef map (optional)
Updated 2026-07-12 00:26:08 View source (.md) rev 5