Appearance
Quickstart with curl
This walkthrough runs the same scenario as our test plan — two users sign up, become friends, and chat — using only curl and jq. Run it before you write app code, to see every response shape.
0. Setup
bash
export API=https://api.chatter.maragato.ca/v1
export CK=ck_your_client_key_here # from your invitation email1. Ana signs up
bash
curl -s -X POST $API/auth/otp -H "X-Client-Key: $CK" \
-H 'Content-Type: application/json' -d '{"phone":"+6580000001"}'
# 204 No Content
ANA=$(curl -s -X POST $API/auth/verify -H "X-Client-Key: $CK" \
-H 'Content-Type: application/json' \
-d '{"phone":"+6580000001","code":"000000","device":{"platform":"ios","name":"curl"}}')
echo $ANA | jq '{isNewUser, profileComplete: .user.profileComplete}'
# { "isNewUser": true, "profileComplete": false }
export ANA_TOKEN=$(echo $ANA | jq -r .accessToken)Complete the profile:
bash
curl -s "$API/usernames/ana_souza/availability" -H "X-Client-Key: $CK" | jq
# { "username": "ana_souza", "available": true }
curl -s -X PATCH $API/me -H "X-Client-Key: $CK" -H "Authorization: Bearer $ANA_TOKEN" \
-H 'Content-Type: application/json' -d '{"displayName":"Ana Souza","username":"ana_souza"}' | jq
# { "id": "01JB…", "displayName": "Ana Souza", "username": "ana_souza", "profileComplete": true, … }2. Ben signs up
bash
BEN=$(curl -s -X POST $API/auth/verify -H "X-Client-Key: $CK" \
-H 'Content-Type: application/json' \
-d '{"phone":"+6580000002","code":"000000","device":{"platform":"ios","name":"curl"}}')
export BEN_TOKEN=$(echo $BEN | jq -r .accessToken)
curl -s -X PATCH $API/me -H "X-Client-Key: $CK" -H "Authorization: Bearer $BEN_TOKEN" \
-H 'Content-Type: application/json' -d '{"displayName":"Ben Tan","username":"ben_tan"}' > /dev/null(You can skip POST /auth/otp in scripts. It is required in the app flow.)
3. Ana finds Ben and sends a friend request
bash
curl -s "$API/users/search?q=ben" -H "X-Client-Key: $CK" -H "Authorization: Bearer $ANA_TOKEN" | jq '.data[] | {id, username, friendshipStatus}'
# { "id": "01JC…", "username": "ben_tan", "friendshipStatus": "none" }
export BEN_ID=$(curl -s "$API/users/search?q=ben_tan" -H "X-Client-Key: $CK" -H "Authorization: Bearer $ANA_TOKEN" | jq -r '.data[0].id')
curl -s -X POST $API/friend-requests -H "X-Client-Key: $CK" -H "Authorization: Bearer $ANA_TOKEN" \
-H 'Content-Type: application/json' -d "{\"userId\":\"$BEN_ID\"}" | jq '{id, status}'
# { "id": "01JD…", "status": "pending" }4. Ben accepts
bash
REQ_ID=$(curl -s "$API/friend-requests?direction=incoming" -H "X-Client-Key: $CK" -H "Authorization: Bearer $BEN_TOKEN" | jq -r '.data[0].id')
curl -s -X POST $API/friend-requests/$REQ_ID/accept -H "X-Client-Key: $CK" -H "Authorization: Bearer $BEN_TOKEN" | jq '{user: .user.username, since}'
# { "user": "ana_souza", "since": "2026-10-22T14:05:00.120Z" }5. Ana opens a chat and sends a message
bash
CONV_ID=$(curl -s -X POST $API/conversations/direct -H "X-Client-Key: $CK" -H "Authorization: Bearer $ANA_TOKEN" \
-H 'Content-Type: application/json' -d "{\"userId\":\"$BEN_ID\"}" | jq -r .id)
curl -s -X POST $API/conversations/$CONV_ID/messages -H "X-Client-Key: $CK" -H "Authorization: Bearer $ANA_TOKEN" \
-H 'Content-Type: application/json' \
-d "{\"clientMessageId\":\"$(uuidgen | tr A-Z a-z)\",\"type\":\"text\",\"body\":\"Hi Ben!\"}" | jq '{seq, body}'
# { "seq": 1, "body": "Hi Ben!" }In the app, send messages over the WebSocket instead. The REST endpoint is a fallback.
6. Ben reads it
bash
curl -s "$API/conversations/$CONV_ID/messages" -H "X-Client-Key: $CK" -H "Authorization: Bearer $BEN_TOKEN" | jq '.data[] | {seq, body}'
curl -s -X POST $API/conversations/$CONV_ID/receipts -H "X-Client-Key: $CK" -H "Authorization: Bearer $BEN_TOKEN" \
-H 'Content-Type: application/json' -d '{"type":"read","seq":1}'
# 204 No ContentAna's view of the conversation now shows Ben's lastReadSeq: 1 — the message is read.
7. Watch events live
Open a WebSocket as Ana in one terminal (using websocat):
bash
websocat "wss://api.chatter.maragato.ca/v1/ws?clientKey=$CK&token=$ANA_TOKEN"Send another message as Ben in a second terminal (repeat step 5 with $BEN_TOKEN). Ana's terminal prints a message.new event.