Skip to content

API Overview

James Wheare edited this page Nov 18, 2013 · 43 revisions

Stream Message ReferenceRPC Reference

The IRCCloud API consists of a stream of JSON messages and a series of RPC methods. The API is accessible via Secure WebSocket (preferred) or HTTPS. Insecure access isn't supported.

Important note

The API is still in flux and not officially supported. Methods, responses, and message formats are liable to change at any time. Feel free to ask questions though.

# Authentication

The first thing a client will need to do to use the API is authenticate. This is done by making an HTTPS POST request to the [[login|API RPC Reference#wiki-unauth-post-login]] endpoint with email and password parameters to acquire a session key.

curl -d email=XXX -d password=XXX "https://www.irccloud.com/chat/login"
{"success":true,"session":"e07910a06a086c83ba41827aa00b26ed","uid":1}

Set this key as the session cookie value for all further requests.

# Stream endpoints

WebSocket

wss://www.irccloud.com/

The following header must be present:
Origin: https://www.irccloud.com

Example request:

GET / HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
User-Agent: [REDACTED]
Cookie: session=[REDACTED]
Sec-WebSocket-Key: [REDACTED]==
Host: www.irccloud.com
Origin: https://www.irccloud.com
Sec-WebSocket-Version: 13

To save on bandwidth, WebSocket connections should support the x-webkit-deflate-frame extension, as currently implemented in Google Chrome and Pywebsocket.

HTTPS

https://www.irccloud.com/chat/stream

No Origin header is needed for the HTTPS stream.

Example request:

GET /chat/stream HTTP/1.1
Connection: keep-alive
Accept-Encoding: gzip,deflate,sdch
User-Agent: [REDACTED]
Cookie: session=[REDACTED]
Host: www.irccloud.com

# Terminology

There are a few potentially ambiguous terms that we use in reference to the API that are worth defining in their normal sense.

Connection

A connection to an IRC network, defined by hostname, port and ssl settings. Uniquely identified by a cid

Buffer

Split into three sub types, this is where events are directed within a connection. We don't use this term in the UI. Uniquely identified by a bid

  • Server log (console) - this is the connection console, where things like the message of the day and connection boilerplate goes as well as other global server messages
  • Channel (channel) - group chat rooms with many members
  • Conversation (conversation) - private messages with a single recipient

Event

Any message directed at a buffer. Uniquely identified by a bid and eid

# User status

One of the first messages to process on the stream is [[stat_user|API Stream Message Reference#wiki-stat_user]]. It provides the authenticated user's name, account details, settings and preferences. Clients can receive this message at any point in a stream session to be notified of updates to any of its properties.

# Processing the initial backlog

# Out of band include

On connecting to the stream, parse and process all messages until the [[oob_include|API Stream Message Reference#wiki-oob_include]] message (oob = out of band). At this point, clients may continue to parse new messages on the stream but must not process them until after fetching and processing all messages retrieved from the out of band url atrribute. This URL expires after a short timeout so should be requested immediately, check the timeout attribute (in ms).

The purpose of this include is so the bulk of the backlog can be fetched with GZIP compression, so the appropriate Accept-Encoding should be sent. The URL provided in the oob_include message is only valid for a few seconds.

The OOB messages contain the full connection and buffer lists, and a limited number of events for each buffer. It will be concluded by a [[backlog_complete|API Stream Message Reference#wiki-backlog_complete]] message (not to be confused with the connection specific [[end_of_backlog|API Stream Message Reference#wiki-end_of_backlog]])

Backlog may also be sent inline. In this case, you'll see an [[oob_skipped|API Stream Message Reference#wiki-oob_skipped]] message instead followed by the full backlog and [[backlog_complete|API Stream Message Reference#wiki-backlog_complete]]. No extra backlog needs to be fetched in this case. Clients should to handle both cases.

# Connections

The OOB include is divided into connection blocks, started by a [[makeserver|API Stream Message Reference#wiki-makeserver]] message that provides the cid, and connection details. and concluded by an [[end_of_backlog|API Stream Message Reference#wiki-end_of_backlog]] message.

A connection's status indicates where it is in the lifecycle of disconnected, connecting, connected, etc. The status value of the [[makeserver|API Stream Message Reference#wiki-makeserver]] message gives the initial status, and all changes are communicated via [[status_changed|API Stream Message Reference#wiki-status_changed]] messages

# Buffers

Within each connection block there'll be a [[makebuffer|API Stream Message Reference#wiki-makebuffer]] message for each of the connection's buffers providing the bid, buffer_type and name for each. This is followed by a list of events with eid values for that buffer. This is limited on the server.

For the console buffer, the name will be * and should never be displayed. Use the connection name for display instead.

If a buffer is listed as deferred then no events will be in the initial stream and must be requested via an HTTPS GET to the [[backlog|API RPC Reference#wiki-get-backlog]] API method when that buffer is selected. Clients should then set the buffer's deferred value to false.

For non deferred buffers, a client can determine whether more backlog can be loaded by comparing the earliest message eid with the min_eid value given in [[makebuffer|API Stream Message Reference#wiki-makebuffer]].

# Archiving

Channel and conversation buffers can be archived. This means they're hidden in the buffer list, under an expandable heading. This allows people to keep their log history around without cluttering up the UI too much.

Conversations that haven't had any activity in them in a while will automatically archive, and when new messages come in they'll unarchive again.

Archived buffers will always be marked as deferred: true

# Channel init

For each channel a user is currently joined to, the backlog will contain a [[channel_init|API Stream Message Reference#wiki-channel_init]] message. This provides the channel members list, topic, mode and a creation date timestamp.

A client should still display channels and backlog that aren't currently joined, but rely on [[channel_init|API Stream Message Reference#wiki-channel_init]] to mark them as active.

# Buffer unread state

A client will need to keep track of which buffers contain unread messages. At the simplest level this involves checking the value of last_seen_eid and comparing it to events received from the server. A client needs to send the last seen event id to the server via the [[heartbeat|API RPC Reference#wiki-post-heartbeat]] API call and keep its local value up to date whenever messages are seen and when [[heartbeat_echo|API Stream Message Reference#wiki-heartbeat_echo]] messages are received.

A seen event is defined as any event received while a user has a buffer selected.

# "Important" messages

Buffers can received many different message types, and only some should mark the buffer as unread. Here's the list of "important" events that trigger an unread state:

  • [[buffer_msg|API Stream Message Reference#wiki-buffer_msg]]
  • [[buffer_me_msg|API Stream Message Reference#wiki-buffer_me_msg]]
  • [[notice|API Stream Message Reference#wiki-notice]]
  • [[channel_invite|API Stream Message Reference#wiki-channel_invite]]
  • [[callerid|API Stream Message Reference#wiki-callerid]]
  • [[wallops|API Stream Message Reference#wiki-wallops]]

notice and channel_invite messages are NOT important if the bid is for a buffer of type console and the message has no from value, OR has a to_chan or to_buffer value of true

Messages with a self value of true are never important

// Algorithm in javascript-ish pseudo code (for brevity)
function isImportant (message) {
    if (message.self) {
        return false;
    }
    var important = [buffer_msg, buffer_me_msg, notice, channel_invite, callerid, wallops];
    if (message.type in important) {
        if (message.type in [notice, channel_invite]) {
            if (!message.from) {
                return false;
            }
            if (isConsoleBuffer(message.bid) && (message.to_chan || message.to_buffer)) {
                return false;
            }
        }
        return true;
    }
}

When last_seen_eid is set via the seenEids value of [[heartbeat_echo|API Stream Message Reference#wiki-heartbeat_echo]], a client must make sure to count all "important" events between the new last seen value and the end, before appropriately marking the buffer as read or unread.

# Ignore

Users are able to specify an ignores list (indicated by [[makeserver|API Stream Message Reference#wiki-makeserver]]). This applies only to [[buffer_msg|API Stream Message Reference#wiki-buffer_msg]], [[buffer_me_msg|API Stream Message Reference#wiki-buffer_me_msg]], [[notice|API Stream Message Reference#wiki-notice]] and [[channel_invite|API Stream Message Reference#wiki-channel_invite]] events. Any of these events that come from a user in the ignore list should NOT result in a last_seen_eid update, nor trigger a notification, nor cause a buffer to be marked as unread.

Ignore masks are of the form <nick>!<user>@<host> and each value may contain the wildcard * symbol.

Parsing reference implementation:

# Reconnecting the stream

If the stream disconnects during an active session, clients should reconnect. This will result in the backlog being fetched again.

How you process this backlog depends on the resumed flag in the [[header|API Stream Message Reference#wiki-header]] message.

If it's true, you can process them as normal messages for a connected stream.

If it's false or not set, you need to parse and read all makeserver and makebuffer messages and compare their properties (e.g. connected, joined, archived) with your stored state. Remove any buffers or servers that are no longer present in the backlog, in case they were deleted while the stream was disconnected.

# Resuming

To save on bandwidth and server load, pass a since_id parameter of the last eid received (they are always sequential) as well as a streamid parameter (sent in the [[header|API Stream Message Reference#wiki-header]] message) to the stream endpoint when you reconnect. e.g. wss://www.irccloud.com/?since_id=12345&streamid=9876 or https://www.irccloud.com/chat/stream?since_id=12345&streamid=9876 This will affect the number of messages returned in the backlog. Always parse and process all backlog messages, but ignore any with an eid that has already been seen for a buffer.

# Idle timeout

You can expect to receive messages from the stream continually and regularly. If no regular messages are due for delivery after a timeout, the server will send an idle message. We keep the stream active to avoid proxy servers from disconnecting, and also to let a client know that the server is still responsive. idle_interval (sent in the [[header|API Stream Message Reference#wiki-header]] message) gives you a maximum time between messages. Clients should restart the stream no messsages are received after that time span.

Clone this wiki locally