Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Send a message via the API

The POST /v1/rooms/{room_id}/send endpoint is one call but the event model behind it has a lot of structure. This page covers the common shapes.

The basic shape#

json
1
2
3
4
5
6
{
  "content": {
    "msgtype": "swp.text",
    "body": "Hello"
  }
}

content is a free-form JSON object; ScaiWave doesn't constrain its shape, only its size (default 64 KB). msgtype is conventional; clients render based on it.

Standard msgtype values#

msgtype Used for
swp.text Plain markdown text.
swp.code A code block with lang field.
swp.media A media attachment. content.media_id + content.thumbnail_id.
swp.system System message — joins, leaves, name changes.
swp.audio_transcript Live transcription output.
swp.todo_change Cross-window todo state broadcast.

You can introduce custom msgtype values for app-specific features; the client just ignores unknown types in the default renderer.

Mentions#

To @mention a participant, include their participant id in a mentions array:

json
1
2
3
4
5
6
7
{
  "content": {
    "msgtype": "swp.text",
    "body": "Hi @alice, can you review?",
    "mentions": ["5e4d…"]
  }
}

The body text contains the human-readable form; the array gives the server enough info to drive notifications. The client's composer populates this automatically when you @ someone.

Threading#

A reply-in-thread sets reply_to_event_id:

json
1
2
3
4
5
6
7
{
  "content": {
    "msgtype": "swp.text",
    "body": "Yeah, I see the problem.",
    "reply_to_event_id": "evt-abc-…"
  }
}

Clients render threaded messages indented or in a separate sidebar. The server doesn't enforce a tree — replies can fork in multiple directions if multiple people reply to the same parent.

Attachments#

Two steps. First upload:

bash
1
2
3
curl -X POST "$BASE/v1/media/upload" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@./photo.jpg"

Returns {data: {media_id, sha256, size, thumbnail_id}}. Then send a message referencing it:

json
1
2
3
4
5
6
7
8
{
  "content": {
    "msgtype": "swp.media",
    "body": "Here's the screenshot",
    "media_id": "med-…",
    "thumbnail_id": "med-thumb-…"
  }
}

The client fetches the media via GET /v1/media/download/{media_id}. Thumbnails are pre-generated for images and videos.

Edits#

Edit an event you sent:

bash
1
2
3
4
curl -X POST "$BASE/v1/rooms/$ROOM_ID/events/$EVENT_ID/edit" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content": {"msgtype": "swp.text", "body": "Corrected text"}}'

The original is preserved in event.original_content. Clients typically show "edited" with a tooltip of the previous version.

You can only edit your own events. After a configurable window (default 24h) edits are rejected.

Redactions#

Hard-delete an event (the body is wiped; the event id remains for audit):

bash
1
2
3
4
curl -X POST "$BASE/v1/rooms/$ROOM_ID/events/$EVENT_ID/redact" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Posted by mistake"}'

You can redact your own. Redacting someone else's requires power_level >= 50 (the redact_other action).

Send-on-behalf (for bots)#

A participant with power_level >= 100 can send on behalf of another participant (bots, scheduled jobs):

json
1
2
3
4
{
  "content": { "msgtype": "swp.text", "body": "Daily standup reminder" },
  "as_participant_id": "<other-participant-id>"
}

The event's sender_id is the spoofed participant; actor_id is the actual API caller (for audit).

Idempotency#

Pass a client-generated event_uuid for idempotency:

json
1
2
3
4
{
  "content": { ... },
  "event_uuid": "<your-uuid-v4>"
}

If the server sees the same event_uuid from the same sender within a 5-minute window, it returns the existing event instead of creating a duplicate. Useful for retries on network failures.

Rate limits#

Default tenant config: 60 messages per minute per participant. Hits return 429 with Retry-After.

Where to go next#

Updated 2026-05-17 13:10:04 View source (.md) rev 1