Curl Cookbook¶
Copy-paste HTTP commands for every Privitty Edge operation.
Replace host, chat IDs, and paths as needed.
Base URL: http://127.0.0.1:7200
Account ID: always 1
Set a helper to reduce repetition:
Health¶
Status¶
# Account e-mail address
$RPC -d '{"jsonrpc":"2.0","method":"get_config","params":[1,"addr"],"id":1}'
# Display name
$RPC -d '{"jsonrpc":"2.0","method":"get_config","params":[1,"displayname"],"id":2}'
# Technical info
$RPC -d '{"jsonrpc":"2.0","method":"get_info","params":[1],"id":3}'
# Connectivity (0=unconfigured, 4000+=connected)
$RPC -d '{"jsonrpc":"2.0","method":"get_connectivity","params":[1],"id":4}'
# Peer count
$RPC -d '{"jsonrpc":"2.0","method":"get_contact_ids","params":[1,0,null],"id":5}'
Invite a peer¶
Share the returned URL with the remote operator.
Join a peer (accept invite)¶
Or pass the https://i.privittytech.com/#… short link.
Send a text message¶
# 1. Lookup contact
$RPC -d '{"jsonrpc":"2.0","method":"lookup_contact_id_by_addr","params":[1,"ops@example.com"],"id":1}'
# 2. Create chat (use contact_id from step 1)
$RPC -d '{"jsonrpc":"2.0","method":"create_chat_by_contact_id","params":[1,12],"id":2}'
# 3. Send (use chat_id from step 2)
$RPC -d '{"jsonrpc":"2.0","method":"send_msg","params":[1,7,{"text":"Batch complete"}],"id":3}'
Send an encrypted file¶
The file must exist at a path inside the container (e.g. /data/report.pdf). See Make a file available in the container below.
CLI via docker exec (recommended — encrypt + send in one step)¶
Same as ./privitty-edge send-file on bare metal:
# Copy file in (if not using a bind mount)
docker cp ~/Desktop/env/environmental_monitoring.pdf privitty-edged:/data/
# Send
docker exec privitty-edged \
privitty-edge --accounts /var/lib/privitty send-file \
--chat 12 \
--file /data/environmental_monitoring.pdf \
--message "Sending a CDR file" \
--allow-forward \
--duration 40
Expected:
Sending 'environmental_monitoring.pdf' (0.0 MB) via Privitty …
allow_download=false allow_forward=true duration=40 min
Encrypted → /data/environmental_monitoring.pdf.prv
File ID : 1
✓ File sent via SMTP (msg_id=22)
Full walkthrough: Example C · Send a File.
curl (two RPC calls — no single combined method)¶
# 1. Get peer contact ID from chat
$RPC -d '{"jsonrpc":"2.0","method":"get_chat_contacts","params":[1,12],"id":1}'
# 2. Encrypt (peer_contact_id=12; allow_download=false, allow_forward=true, 40 min)
$RPC -d '{"jsonrpc":"2.0","method":"privitty_send_file","params":[1,12,12,"/data/environmental_monitoring.pdf",false,true,40],"id":2}'
# 3. Deliver .prv attachment (use encrypted_path from step 2)
$RPC -d '{"jsonrpc":"2.0","method":"send_msg","params":[1,12,{"text":"Sending a CDR file","file":"/data/environmental_monitoring.pdf.prv","viewtype":"File"}],"id":3}'
One-liner (encrypt + send):
CHAT=12
FILE="/data/environmental_monitoring.pdf"
MSG="Sending a CDR file"
PEER=$(curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"get_chat_contacts\",\"params\":[1,${CHAT}],\"id\":1}" \
| jq '[.result[] | select(. != 1)][0]')
PRV=$(curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"privitty_send_file\",\"params\":[1,${CHAT},${PEER},\"${FILE}\",false,true,40],\"id\":2}" \
| jq -r '.result.encrypted_path')
curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"send_msg\",\"params\":[1,${CHAT},{\"text\":\"${MSG}\",\"file\":\"${PRV}\",\"viewtype\":\"File\"}],\"id\":3}" \
| jq .
License required
File send requires an active license. See License Management.
Make a file available in the container¶
| Method | When to use | Host → container |
|---|---|---|
| Bind mount | Production; files dropped by SCADA/MES | -v ~/privitty-outbox:/data at docker run |
docker cp |
Quick test; container already running | docker cp file.pdf privitty-edged:/data/ |
| Volume staging | No bind mount; no recreate | Copy into privitty-data via Alpine sidecar |
Bind mount — set at container start only:
mkdir -p ~/privitty-outbox
docker run -d ... -v privitty-data:/var/lib/privitty -v ~/privitty-outbox:/data privitty/edge:latest
cp ~/Desktop/report.pdf ~/privitty-outbox/ # appears as /data/report.pdf
docker cp — works on a running container:
Warning
A bind mount only works if you included -v host/path:/data when the container was created. Adding it later requires recreating the container (the privitty-data volume is kept).
Details: Example C · Send a File.
List chats¶
The CLI command privitty-edge chats prints:
ID T Name Unread
──────────────────────────────────────────────────────────────
3 @ factory-gw-01
7 # ops-team (2 new)
12 @ sensor-node-02
15 # audit-log (1 new)
Reproduce the same information with curl using this two-call sequence:
Step 1 — Get all chat IDs:
curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"get_chatlist_entries","params":[1,null,null,null],"id":1}'
Step 2 — Get name and type for those IDs:
curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"get_chatlist_items_by_entries","params":[1,[3,7,12,15]],"id":2}' \
| jq '.result | to_entries | sort_by(.key | tonumber)
| map({
id: (.key | tonumber),
type: (if .value.chatType == 120 then "group"
elif .value.chatType == 130 then "broadcast"
else "1:1" end),
name: .value.name,
unread: .value.freshMessageCounter
})'
Output matches the CLI table:
[
{"id": 3, "type": "1:1", "name": "factory-gw-01", "unread": 0},
{"id": 7, "type": "group", "name": "ops-team", "unread": 2},
{"id": 12, "type": "1:1", "name": "sensor-node-02", "unread": 0},
{"id": 15, "type": "group", "name": "audit-log", "unread": 1}
]
chatType |
CLI symbol | JSON type |
|---|---|---|
100 |
@ |
"1:1" |
120 |
# |
"group" |
130 |
≫ |
"broadcast" |
One-liner — chain both calls (requires jq):
IDS=$(curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"get_chatlist_entries","params":[1,null,null,null],"id":1}' \
| jq '.result')
curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"get_chatlist_items_by_entries\",\"params\":[1,${IDS}],\"id\":2}" \
| jq '.result | to_entries | sort_by(.key | tonumber)
| map({id: (.key|tonumber), type: (if .value.chatType==120 then "group" elif .value.chatType==130 then "broadcast" else "1:1" end), name: .value.name, unread: .value.freshMessageCounter})'
Use the id values from this output as the chat_id in the next section.
List messages in a chat¶
The CLI command privitty-edge msgs <chat_id> prints:
══ 2026-05-27 ══════════════════════════════════════════════
[ 81] 10:02 sensor-node-02
Batch started
[ 82] 10:05 sensor-node-02
Sensor reading 42.7°C
[ 83] 10:08 Me ✓✓
🔒 report.csv.prv (38 KB)
→ privitty-viewer --msg-id 83
[ 84] 10:10 Me 👁
Batch complete
Reproduce the same information with curl using this two-call sequence:
Step 1 — Get message IDs for chat (replace 7 with your chat ID):
curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"get_message_ids","params":[1,7,false,false],"id":1}'
Step 2 — Fetch message details (paste the IDs from Step 1):
curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"get_messages","params":[1,[81,82,83,84]],"id":2}' \
| jq '.result | to_entries | sort_by(.key | tonumber)
| map({
msg_id: (.key | tonumber),
time: (.value.timestamp | strftime("%H:%M") // "??:??"),
from: (if .value.fromId == 1 then "Me"
else (.value.sender.displayName // "?") end),
state: (if .value.state == 1 then "unread"
elif .value.state == 10 then "pending"
elif .value.state == 20 then "sent ✓"
elif .value.state == 26 then "delivered ✓✓"
elif .value.state == 28 then "read 👁"
else "" end),
text: .value.text,
file: .value.file,
file_size: .value.fileBytes,
encrypted: (.value.file // "" | endswith(".prv"))
})'
Output matches the CLI display:
[
{
"msg_id": 81,
"time": "10:02",
"from": "sensor-node-02",
"state": "read 👁",
"text": "Batch started",
"file": null,
"file_size": 0,
"encrypted": false
},
{
"msg_id": 83,
"time": "10:08",
"from": "Me",
"state": "delivered ✓✓",
"text": "Report attached",
"file": "/var/lib/privitty/blobs/report.csv.prv",
"file_size": 38912,
"encrypted": true
}
]
state |
CLI symbol | JSON state |
|---|---|---|
| Fresh / unread | (none) | "unread" |
| Pending | → |
"pending" |
| Delivered to server | ✓ |
"sent ✓" |
| Delivered to device | ✓✓ |
"delivered ✓✓" |
| Read | 👁 |
"read 👁" |
One-liner — chain both calls for a given chat ID (replace 7):
MSGIDS=$(curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"get_message_ids","params":[1,7,false,false],"id":1}' \
| jq '.result')
curl -s -X POST http://127.0.0.1:7200/rpc \
-H "Content-Type: application/json" \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"get_messages\",\"params\":[1,${MSGIDS}],\"id\":2}" \
| jq '.result | to_entries | sort_by(.key|tonumber)
| map({msg_id:(.key|tonumber), from:(if .value.fromId==1 then "Me" else (.value.sender.displayName//"?") end), state:.value.state, text:.value.text, encrypted:(.value.file//""|endswith(".prv"))})'
View an encrypted file
Any message where "encrypted": true can be opened directly with:
privitty/edge:latest-viewer image. The file is decrypted in memory — no plaintext ever touches the filesystem.
Revoke file access¶
# 1. Load message to get .prv path
$RPC -d '{"jsonrpc":"2.0","method":"get_messages","params":[1,[42]],"id":1}'
# 2. Resolve file ID (use file path from message)
$RPC -d '{"jsonrpc":"2.0","method":"privitty_get_file_id_by_path","params":[1,"/path/to/file.prv"],"id":2}'
# 3. Revoke (chat_id=7, file_id=42, peer_contact_id=12)
$RPC -d '{"jsonrpc":"2.0","method":"privitty_revoke_file_access","params":[1,7,42,12],"id":3}'
SSE event stream¶
See Example D · SSE Streaming for filtered Python/shell clients.
License (via CLI inside container)¶
docker exec privitty-edged \
privitty-edge --accounts /var/lib/privitty license status
docker exec privitty-edged \
privitty-edge --accounts /var/lib/privitty \
license activate "https://plm.privittytech.com/v1/license/TOKEN"
See License Management.
End-to-end examples¶
| Walkthrough | Link |
|---|---|
| A · First boot | examples/first-boot.md |
| B · Invite & send | examples/invite-and-send.md |
| C · Send a file | examples/send-file.md |
| D · SSE streaming | examples/sse-streaming.md |
| E · License | examples/license.md |