Quick start
Three requests to your first message
Working with the API comes down to signing in, going online and an endless event loop.
1
Sign in
POST your UIN and password as a form to /auth/clientLogin. You get back the token token.a.
2
Go online
Call /aim/startSession with that token. You get aimsid — the key to every other method — plus your buddy list.
3
Listen
Poll /aim/fetchEvents in a loop. The request waits up to a minute and returns the moment something happens: a message, a status change, “typing…”.
No UIN yet? Sign up on Jimm.online in a minute. For a bot, create a separate account.
🤖 An echo bot in 20 lines
A working example: the bot goes online and answers every message with its own text. Put in your UIN and password and run it.
Python
Node.js
Copy
import re, time, requests
API = "https://jimm.online/webapi"
UIN, PASSWORD = "123456789", "secret"
def call(path, **params):
r = requests.get(API + path, params={"f": "json", **params}, timeout=75)
resp = r.json()["response"]
if resp["statusCode"] != 200:
raise RuntimeError(f'{resp["statusCode"]} {resp["statusText"]}')
return resp["data"]
login = requests.post(API + "/auth/clientLogin", data={
"s": UIN, "pwd": PASSWORD, "devId": "echo-bot", "f": "json"}).json()
token = login["response"]["data"]["token"]["a"]
aimsid = call("/aim/startSession", a=token, events="im", clientName="EchoBot")["aimsid"]
seq = 0
while True:
batch = call("/aim/fetchEvents", aimsid=aimsid, seqNum=seq, timeout=60000)
for ev in batch["events"]:
if ev["type"] == "im":
text = re.sub(r"<[^>]+>", "", ev["eventData"]["message"])
call("/im/sendIM", aimsid=aimsid, t=ev["eventData"]["source"]["aimId"],
message="Echo: " + text, offlineIM="true")
seq = batch["lastSeqNum"]
time.sleep(batch["timeToNextFetch"] / 1000)
Copy
// Node.js 18+ (fetch is built in). Run as an .mjs file.
const API = 'https://jimm.online/webapi';
const UIN = '123456789', PASSWORD = 'secret';
async function call(path, params) {
const res = await fetch(`${API}${path}?${new URLSearchParams({ f: 'json', ...params })}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(`${response.statusCode} ${response.statusText}`);
return response.data;
}
const login = await fetch(`${API}/auth/clientLogin`, {
method: 'POST',
body: new URLSearchParams({ s: UIN, pwd: PASSWORD, devId: 'echo-bot', f: 'json' }),
}).then((r) => r.json());
const token = login.response.data.token.a;
const { aimsid } = await call('/aim/startSession', { a: token, events: 'im', clientName: 'EchoBot' });
let seqNum = 0;
for (;;) {
const { events, lastSeqNum, timeToNextFetch } = await call('/aim/fetchEvents', { aimsid, seqNum, timeout: 60000 });
for (const { type, eventData } of events) {
if (type !== 'im') continue;
const text = eventData.message.replace(/<[^>]+>/g, '');
await call('/im/sendIM', { aimsid, t: eventData.source.aimId, message: `Echo: ${text}`, offlineIM: 'true' });
}
seqNum = lastSeqNum;
await new Promise((resolve) => setTimeout(resolve, timeToNextFetch));
}
How it works
What to know before the first line of code
clientLogin
token
startSession
aimsid
fetchEvents ⟳
endSession
The response envelope
Every response is wrapped in {"response": {"statusCode", "statusText", "data"}}. Judge success by statusCode, not the HTTP status: an undelivered message (602) or a rate limit (430) comes back on HTTP 200. The payload is in data.
Token and aimsid
token.a from clientLogin proves who you are. It lasts 24 hours by default, or a year with tokenType=longterm, so you don’t have to keep the password. aimsid from startSession is one particular “online” session: it lives while you poll for events and dies after 150 seconds of silence. One UIN can hold several sessions at once.
Long-polling
There are no websockets: fetchEvents simply holds the request open until there is an event (up to 60 s). After it returns, wait timeToNextFetch ms and ask again with seqNum = lastSeqNum, and you never miss an event. Set your HTTP client’s timeout above 60 s, or it will hang up before the answer arrives.
GET, POST and parameters
Almost every method is a GET with query parameters. The same parameters work as a POSTed form too, except /auth/clientLogin (POST form only) and the icon upload (raw bytes). Choose the response format with f: json (default), xml or amf3. Add c=functionName for JSONP.
From a browser
The API answers with CORS headers, so fetch from a web page works. Use GET methods: they are “simple” requests and need no CORS preflight. Send passwords straight to the API server, never through a third party.
Rate limits
The limits are the same as for regular ICQ clients, and they apply per account, not per connection. Go over and you get statusCode 430 with a Retry-After header (seconds to wait) and a rateLimit event. Don’t retry sooner, or the limit drags on.
House rules
Send a meaningful devId and clientName — it helps us help you when something breaks.
Bots don’t message people who never wrote to them. Spam accounts get blocked.
Don’t store other people’s passwords. Keep the token and ask for the password again when it expires.
Call endSession when your client closes, so contacts see you leave right away.
Live console
Try it right here
Sign in with your UIN and every method below gets a “Run” button. Requests go from your browser straight to the API server, like any client’s. The site never sees or stores your password.
Online as
Sign off
Event stream
0
Pause
Clear
All quiet. Message yourself from another client and the event shows up here.
The console acts as you: messages you send and buddy list changes are real.
Reference · 33
All methods
Open a method to see its parameters, response and code samples.
Sign-in
Trade a UIN and password for a token. The password travels once; the token does the rest.
POST
/auth/clientLogin
Sign in with a UIN and password
No auth
Checks a UIN and password and returns the token token.a, which startSession takes. The body is a plain application/x-www-form-urlencoded form: the server does not read JSON and answers 400. You can keep the token instead of the password; by default it lives 24 hours.
Parameters
Name Description
s
string · in body
required
The UIN (or username).
pwd
string · in body
required
The password (or password).
devId
string · in body
Your client’s name. Shows up in the server log; defaults to WebAIM.
tokenType
string · in body
Token lifetime: shortterm (24 h, the default), longterm (365 days) or a number of seconds.
f
string · in body
Response format. A POST sends it in the body.
jsonxmlamf3
Errors
330 Wrong UIN or password (statusDetailCode: 3011, HTTP 401).
460 UIN or password missing (HTTP 400).
462 Bad tokenType (HTTP 400).
Example request
cURL
JavaScript
Python
Copy
curl -X POST "https://jimm.online/webapi/auth/clientLogin" \
--data-urlencode "s=123456789" \
--data-urlencode "pwd=$PASSWORD" \
--data-urlencode "devId=my-client" \
--data-urlencode "f=json"
Copy
const res = await fetch('https://jimm.online/webapi/auth/clientLogin', {
method: 'POST',
body: new URLSearchParams({ s: "123456789", pwd: password, devId: "my-client", f: "json" }),
});
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.post("https://jimm.online/webapi/auth/clientLogin", data={"s": "123456789", "pwd": password, "devId": "my-client", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"token": {
"a": "AAAAAGdQ…base64url…",
"expiresIn": "86400"
},
"loginId": "123456789",
"screenName": "123456789",
"sessionSecret": "q1w2e3…",
"hostTime": 1761130000,
"tokenExpiresIn": 86400
}
#clientLogin · Link to this method
GET
/auth/getInfo
Check a token
Token
Tells whether a saved token is still good and whose it is. Handy at client start-up: anything but 200 means ask for the password again.
Parameters
Name Description
a
string
required
The token from clientLogin.
reqAuthFreshness
integer
Maximum age of the sign-in, in seconds (default 86400). Older means 330.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
401 Token refused: expired, damaged or not from clientLogin.
330 The sign-in is older than reqAuthFreshness allows.
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/auth/getInfo" \
--data-urlencode "a=$TOKEN" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ a: token, f: "json" });
const res = await fetch(`https://jimm.online/webapi/auth/getInfo?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/auth/getInfo", params={"a": token, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"userData": {
"loginId": "123456789",
"displayName": "123456789"
}
}
#getInfo · Link to this method
Session & events
Going online, long-polling the event stream, and signing off.
GET
/aim/startSession
Go online
Token
Opens a session and puts you online, so your contacts see you arrive. Returns aimsid, which every other method takes. events lists what you want to hear about. The starting state (buddy list, your own info) comes right in the response and again as the first events of the stream. Offline messages arrive as offlineIM events and are deleted from the server as they go, so keep them yourself. Stop polling and the session closes after 150 seconds.
Parameters
Name Description
a
string
required
The token from clientLogin.
events
string
Comma-separated events to subscribe to. Defaults to buddylist,presence,im,sentIM.
clientName
string
Your client’s name.
clientVersion
string
Your client’s version.
timeout
integer
Default long-poll timeout, in seconds (60).
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
401 Token missing or expired.
503 The server could not open a session.
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/aim/startSession" \
--data-urlencode "a=$TOKEN" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ a: token, f: "json" });
const res = await fetch(`https://jimm.online/webapi/aim/startSession?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/aim/startSession", params={"a": token, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"aimsid": "0123456789abcdef.123456789",
"ts": 1761130000,
"fetchTimeout": 60000,
"timeToNextFetch": 500,
"fetchBaseURL": "https://jimm.online/webapi/aim/fetchEvents?aimsid=0123456789abcdef.123456789&seqNum=0",
"myInfo": {
"aimId": "123456789",
"displayId": "123456789",
"friendly": "123456789",
"state": "online",
"userType": "icq",
"bot": false,
"service": "icq",
"capabilities": [],
"buddyIcon": "https://jimm.online/webapi/expressions/get?t=123456789&type=buddyIcon"
},
"events": {
"buddylist": {
"groups": [
{
"name": "Друзья",
"id": 1,
"buddies": [
{
"aimId": "987654321",
"displayId": "987654321",
"friendly": "Вася",
"state": "online",
"statusMsg": "на связи",
"onlineTime": 1761120000,
"userType": "icq",
"service": "icq",
"buddyIcon": "https://jimm.online/webapi/expressions/get?t=987654321&type=buddyIcon",
"bot": false
}
]
}
]
}
},
"wellKnownUrls": {
"webApiBase": "https://jimm.online/webapi/",
"fetchBaseURL": "https://jimm.online/webapi/aim/fetchEvents"
}
}
#startSession · Link to this method
GET
/aim/fetchEvents
Fetch events (long-poll)
aimsid
The client’s main loop. The request waits until there are events newer than seqNum or timeout runs out, then returns them as a batch (possibly empty). Make the next request with seqNum = lastSeqNum after timeToNextFetch ms. Every call keeps the session alive. The server keeps up to the last 1000 events.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
seqNum
integer
The last event number you saw; 0 for everything.
timeout
integer
How long to wait, in milliseconds , 60000 at most.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
401 The session is closed or expired. Start over with startSession.
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/aim/fetchEvents" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/aim/fetchEvents?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/aim/fetchEvents", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"events": [
{
"type": "im",
"seqNum": 7,
"timestamp": 1761130042,
"eventData": {
"source": {
"aimId": "987654321",
"displayId": "987654321",
"friendly": "Вася",
"userType": "icq",
"state": "online"
},
"message": "Привет! Как дела?",
"msgId": "9c2e41d07a3b55f1",
"timestamp": 1761130042,
"imf": "plain",
"autoresponse": false
}
}
],
"lastSeqNum": 7,
"timeToNextFetch": 500,
"fetchBaseURL": "https://jimm.online/webapi/aim/fetchEvents?aimsid=0123456789abcdef.123456789&seqNum=7"
}
#fetchEvents · Link to this method
GET
/aim/endSession
Sign off
aimsid
Closes the session; your contacts see you leave. In a browser, navigator.sendBeacon from pagehide works well.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/aim/endSession" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/aim/endSession?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/aim/endSession", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#endSession · Link to this method
GET
/aim/startOSCARSession
Address and cookie for native OSCAR
Token
For a full OSCAR-over-TCP client: sign in over HTTP, then connect straight to BOS with the returned host, port and cookie, skipping the in-protocol password step.
Parameters
Name Description
a
string
required
The token from clientLogin.
useTLS
boolean
Ask for the TLS port. Falls back to plain if the server has none.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
401 Token missing or expired.
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/aim/startOSCARSession" \
--data-urlencode "a=$TOKEN" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ a: token, f: "json" });
const res = await fetch(`https://jimm.online/webapi/aim/startOSCARSession?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/aim/startOSCARSession", params={"a": token, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"host": "icq.jimm.online",
"port": 5190,
"cookie": "AAAAAGdQ…base64…"
}
#startOSCARSession · Link to this method
Messaging
Sending messages, the typing indicator and this session’s history.
GET
/im/sendIM
Send a message
aimsid
Accepts GET or a POSTed form. From a browser prefer GET: it is a “simple” request and needs no CORS preflight. Pass offlineIM=true so a message to someone who is offline is stored and delivered when they sign in. It changes nothing for an online recipient, so it is safe to always send. Your own sessions get a copy as a sentIM event.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
t
string
required
Recipient’s UIN.
message
string
required
The text. Up to ~4000 bytes.
offlineIM
boolean
Store it if the recipient is offline.
autoResponse
string
1 marks an auto-reply (an away message).
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
602 Not delivered: the recipient is offline and no offlineIM, their offline box is full, or you blocked them. HTTP is still 200 — read statusCode.
430 Too fast. Wait Retry-After seconds.
400 Missing t or message.
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/im/sendIM" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "t=987654321" \
--data-urlencode "message=Привет! 👋" \
--data-urlencode "offlineIM=true" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, t: "987654321", message: "Привет! 👋", offlineIM: "true", f: "json" });
const res = await fetch(`https://jimm.online/webapi/im/sendIM?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/im/sendIM", params={"aimsid": aimsid, "t": "987654321", "message": "Привет! 👋", "offlineIM": "true", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"msgId": "5f1c0e2a-9b3d-4c11-8000-0a1b2c3d4e5f",
"state": "delivered",
"timestamp": 1761130050
}
#sendIM · Link to this method
GET
/im/setTyping
Typing indicator
aimsid
Tells the other side you are typing. Sent only if their client asked for typing notices; otherwise the server quietly answers HTTP 200 with an empty body, which is not an error. Don’t send more than once every couple of seconds.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
t
string
required
The other side’s UIN.
typingStatus
string
typing, typed (paused) or none (cleared).
typingtypednone
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/im/setTyping" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "t=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, t: "987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/im/setTyping?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/im/setTyping", params={"aimsid": aimsid, "t": "987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#setTyping · Link to this method
GET
/imlog/fetchStoredIMs
This session’s history
aimsid
Messages with one person that went through this session. The server keeps no history across sessions: sign in again and the list starts empty. Keep permanent history on the client.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
to
string
required
The other side’s UIN.
nToGet
integer
How many to return.
sortOrder
string
asc or desc.
ascdesc
startTime
integer
Not before (unix time).
endTime
integer
Not after (unix time).
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/imlog/fetchStoredIMs" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "to=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, to: "987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/imlog/fetchStoredIMs?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/imlog/fetchStoredIMs", params={"aimsid": aimsid, "to": "987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"msgs": [
{
"sender": "987654321",
"message": "Привет!",
"msgId": "9c2e41d07a3b55f1",
"date": 1761130042
}
]
}
#fetchStoredIMs · Link to this method
Presence & profile
Your own status, x-status and profile, and other people’s presence.
GET
/presence/get
Presence of people or the whole list
aimsid
With bl=1, the whole buddy list with live presence. With t, the presence of given people (up to 32), whether or not they are on your list — good for a preview card before adding someone.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
t
string
UINs, comma-separated (or repeat t). Up to 32.
bl
string
1 returns the whole buddy list by group.
profileMsg
string
1 adds the profile text.
mdir
boolean
Add directory data (name, city).
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/presence/get" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/presence/get?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/presence/get", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"users": [
{
"aimId": "987654321",
"displayId": "987654321",
"friendly": "Вася",
"state": "online",
"statusMsg": "на связи",
"onlineTime": 1761120000,
"userType": "icq",
"service": "icq",
"buddyIcon": "https://jimm.online/webapi/expressions/get?t=987654321&type=buddyIcon"
}
]
}
#getPresence · Link to this method
GET
/presence/setState
Change status
aimsid
The main status: online, away, do not disturb, occupied, invisible. Away can carry an away message.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
view
string
required
The new status (or state).
onlineawaydndoccupiedinvisible
awayMsg
string
Away message (for away).
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/presence/setState" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "view=away" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, view: "away", f: "json" });
const res = await fetch(`https://jimm.online/webapi/presence/setState?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/presence/setState", params={"aimsid": aimsid, "view": "away", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"aimId": "123456789",
"displayId": "123456789",
"state": "away",
"awayMsg": "Скоро вернусь",
"statusMsg": "",
"userType": "icq",
"onlineTime": 1761130000
}
#setState · Link to this method
GET
/presence/setStatus
Status text and x-status
aimsid
Sets the line under your name and the mood icon (x-status). A parameter changes only if present: mood= with an empty value clears the x-status, no mood at all leaves it alone. Mood codes are in the reference .
Parameters
Name Description
aimsid
string
required
Session id from startSession.
statusMsg
string
Status text. Empty clears it.
mood
string
X-status code. Empty clears it.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
400 Unknown mood or text too long.
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/presence/setStatus" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/presence/setStatus?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/presence/setStatus", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#setStatus · Link to this method
GET
/presence/getProfile
A user’s profile
aimsid
Profile text (“about me”). Without sn, your own.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
sn
string
Whose profile.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/presence/getProfile" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/presence/getProfile?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/presence/getProfile", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"screenName": "987654321",
"profile": "Сижу в аське с 2003 года",
"lastUpdated": 0
}
#getProfile · Link to this method
GET
/presence/setProfile
Update your profile
aimsid
Replaces your profile text. Up to 4 KB.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
profile
string
required
The new text.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/presence/setProfile" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "profile=Сижу в аське с 2003 года" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, profile: "Сижу в аське с 2003 года", f: "json" });
const res = await fetch(`https://jimm.online/webapi/presence/setProfile?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/presence/setProfile", params={"aimsid": aimsid, "profile": "Сижу в аське с 2003 года", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#setProfile · Link to this method
Buddy list
The buddy list lives on the server: groups, buddies, nicknames. Every change arrives as a buddylist event in all your sessions.
GET
/buddylist/addBuddy
Add a buddy
aimsid
Adds someone to a group (Buddies by default), creating the group if needed. An empty data means success; otherwise data.resultCode says why, e.g. alreadyExists.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
buddy
string
required
The UIN.
group
string
The group.
preAuthorized
boolean
Pre-authorize this person to add you.
authorizationMsg
string
Authorization request text.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/buddylist/addBuddy" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "buddy=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, buddy: "987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/buddylist/addBuddy?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/buddylist/addBuddy", params={"aimsid": aimsid, "buddy": "987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#addBuddy · Link to this method
GET
/buddylist/removeBuddy
Remove a buddy
aimsid
Removes a buddy from one group, or from all with allGroups=1.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
buddy
string
required
The UIN.
group
string
Which group.
allGroups
boolean
Remove from every group.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/buddylist/removeBuddy" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "buddy=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, buddy: "987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/buddylist/removeBuddy?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/buddylist/removeBuddy", params={"aimsid": aimsid, "buddy": "987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#removeBuddy · Link to this method
GET
/buddylist/moveBuddy
Move a buddy
aimsid
Moves a buddy to another group and/or before another buddy.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
buddy
string
required
The UIN.
group
string
required
Current group.
newGroup
string
New group.
beforeBuddy
string
Place before this UIN.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/buddylist/moveBuddy" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "buddy=987654321" \
--data-urlencode "group=Друзья" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, buddy: "987654321", group: "Друзья", f: "json" });
const res = await fetch(`https://jimm.online/webapi/buddylist/moveBuddy?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/buddylist/moveBuddy", params={"aimsid": aimsid, "buddy": "987654321", "group": "Друзья", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#moveBuddy · Link to this method
GET
/buddylist/setBuddyAttribute
Buddy nickname
aimsid
Your private name for a buddy (only you see it). Comes back as friendly.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
t
string
required
The UIN.
friendly
string
The nickname. Empty clears it.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/buddylist/setBuddyAttribute" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "t=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, t: "987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/buddylist/setBuddyAttribute?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/buddylist/setBuddyAttribute", params={"aimsid": aimsid, "t": "987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#setBuddyAttribute · Link to this method
GET
/buddylist/addGroup
Create a group
aimsid
Creates a group. Calling it twice is harmless.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
group
string
required
The name.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/buddylist/addGroup" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "group=Работа" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, group: "Работа", f: "json" });
const res = await fetch(`https://jimm.online/webapi/buddylist/addGroup?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/buddylist/addGroup", params={"aimsid": aimsid, "group": "Работа", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#addGroup · Link to this method
GET
/buddylist/renameGroup
Rename a group
aimsid
Renames a group.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
oldGroup
string
required
Current name.
newGroup
string
required
New name.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/buddylist/renameGroup" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "oldGroup=Работа" \
--data-urlencode "newGroup=Коллеги" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, oldGroup: "Работа", newGroup: "Коллеги", f: "json" });
const res = await fetch(`https://jimm.online/webapi/buddylist/renameGroup?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/buddylist/renameGroup", params={"aimsid": aimsid, "oldGroup": "Работа", "newGroup": "Коллеги", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#renameGroup · Link to this method
GET
/buddylist/removeGroup
Remove a group
aimsid
Removes a group.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
group
string
required
The name.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/buddylist/removeGroup" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "group=Коллеги" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, group: "Коллеги", f: "json" });
const res = await fetch(`https://jimm.online/webapi/buddylist/removeGroup?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/buddylist/removeGroup", params={"aimsid": aimsid, "group": "Коллеги", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#removeGroup · Link to this method
GET
/buddylist/setGroupAttribute
Collapse or expand a group
aimsid
Stores whether a group is collapsed, so all your clients show it the same way.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
group
string
required
The name.
collapsed
boolean
required
Collapsed or not.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/buddylist/setGroupAttribute" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "group=Друзья" \
--data-urlencode "collapsed=true" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, group: "Друзья", collapsed: "true", f: "json" });
const res = await fetch(`https://jimm.online/webapi/buddylist/setGroupAttribute?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/buddylist/setGroupAttribute", params={"aimsid": aimsid, "group": "Друзья", "collapsed": "true", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#setGroupAttribute · Link to this method
GET
/aim/addTempBuddy
Watch presence without adding
aimsid
Subscribes this session to presence of people not on your list, until the session ends. Up to 160 people.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
t
string
required
Comma-separated UINs.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
400 Empty list or over 160.
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/aim/addTempBuddy" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "t=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, t: "987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/aim/addTempBuddy?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/aim/addTempBuddy", params={"aimsid": aimsid, "t": "987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#addTempBuddy · Link to this method
GET
/aim/removeTempBuddy
Stop watching
aimsid
Undoes addTempBuddy.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
t
string
required
Comma-separated UINs.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/aim/removeTempBuddy" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "t=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, t: "987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/aim/removeTempBuddy?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/aim/removeTempBuddy", params={"aimsid": aimsid, "t": "987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#removeTempBuddy · Link to this method
Preferences & privacy
Server-side account preferences and the allow and block lists.
GET
/preference/get
Account preferences
aimsid
Server-side preferences: 1 on, 0 off. The same values come as the preference event.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/preference/get" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/preference/get?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/preference/get", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"showGroups": 1,
"showOffLineBuddies": 1,
"acceptOffLineIM": 1,
"discloseTyping": 1,
"viewIMTimestamps": 1
}
#getPreferences · Link to this method
GET
/preference/set
Change preferences
aimsid
Each preference is its own parameter, 1 or 0. Returns only what changed.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
acceptOffLineIM
string
Accept offline messages.
discloseTyping
string
Show others that you are typing.
showOffLineBuddies
string
Show offline buddies.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/preference/set" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/preference/set?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/preference/set", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#setPreferences · Link to this method
GET
/preference/getPermitDeny
Who can reach you
aimsid
The privacy mode and the allow and block lists.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/preference/getPermitDeny" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/preference/getPermitDeny?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/preference/getPermitDeny", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"pdMode": "denySome",
"blocks": [
"555555"
]
}
#getPermitDeny · Link to this method
GET
/preference/setPermitDeny
Blocking and privacy mode
aimsid
Changes the mode and/or adds and removes people from the lists. Lists are comma-separated UINs.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
pdMode
string
permitAll everyone, denySome all but blocked, permitSome only allowed, permitOnList only buddies, denyAll nobody.
permitAlldenySomepermitSomepermitOnListdenyAll
pdBlock
string
Block.
pdBlockRemove
string
Unblock.
pdAllow
string
Allow.
pdAllowRemove
string
Remove from allowed.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/preference/setPermitDeny" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/preference/setPermitDeny?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/preference/setPermitDeny", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"pdMode": "denySome",
"blocks": [
"555555"
]
}
#setPermitDeny · Link to this method
Member directory
The member directory: search by UIN or name, and directory profiles.
GET
/memberDir/search
Find people
aimsid
match is comma-separated key=value pairs. keyword finds an exact UIN plus keyword matches; firstName and lastName search names. You never appear in your own results.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
match
string
required
What to look for.
nToGet
integer
How many (default 100).
nToSkip
integer
How many to skip.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/memberDir/search" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "match=keyword=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, match: "keyword=987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/memberDir/search?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/memberDir/search", params={"aimsid": aimsid, "match": "keyword=987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"results": {
"nTotal": 1,
"nSkipped": 0,
"nProfiles": 1,
"infoArray": [
{
"profile": {
"aimId": "987654321",
"displayId": "987654321",
"firstName": "Василий",
"lastName": "Пупкин",
"city": "Киев",
"country": "UA"
}
}
]
}
}
#memberDirSearch · Link to this method
GET
/memberDir/get
Directory profile
aimsid
Directory profiles (name, city, country) of up to 20 people. Without t, your own.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
t
string
Comma-separated UINs.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/memberDir/get" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, f: "json" });
const res = await fetch(`https://jimm.online/webapi/memberDir/get?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/memberDir/get", params={"aimsid": aimsid, "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"infoArray": [
{
"profile": {
"aimId": "987654321",
"displayId": "987654321",
"firstName": "Василий",
"lastName": "Пупкин",
"city": "Киев",
"country": "UA"
}
}
]
}
#memberDirGet · Link to this method
GET
/memberDir/update
Update your directory profile
aimsid
Each field is its own set=key=value. Fields you leave out stay as they are.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
set
string
required
A field: firstName, lastName. Repeatable.
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/memberDir/update" \
--data-urlencode "aimsid=$AIMSID" \
--data-urlencode "set=firstName=Иван" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ aimsid, set: "firstName=Иван", f: "json" });
const res = await fetch(`https://jimm.online/webapi/memberDir/update?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/memberDir/update", params={"aimsid": aimsid, "set": "firstName=Иван", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
#memberDirUpdate · Link to this method
Buddy icons
Fetching and uploading buddy icons.
GET
/expressions/get
A user’s buddy icon
No auth
No auth needed. type=buddyIcon serves the image itself, ready for <img src>. Without type, JSON with the link.
Parameters
Name Description
t
string
required
The UIN.
type
string
buddyIcon returns the image.
buddyIconbigBuddyIcon
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Errors
Example request
cURL
JavaScript
Python
Copy
curl -G "https://jimm.online/webapi/expressions/get" \
--data-urlencode "t=987654321" \
--data-urlencode "f=json"
Copy
const params = new URLSearchParams({ t: "987654321", f: "json" });
const res = await fetch(`https://jimm.online/webapi/expressions/get?${params}`);
const { response } = await res.json();
if (response.statusCode !== 200) throw new Error(response.statusText);
Copy
import requests
r = requests.get("https://jimm.online/webapi/expressions/get", params={"t": "987654321", "f": "json"})
resp = r.json()["response"]
assert resp["statusCode"] == 200, resp["statusText"]
print(resp["data"])
Response What response.data holds
{
"expressions": [
{
"type": "bigBuddyIcon",
"url": "https://jimm.online/webapi/expressions/get?t=987654321&type=buddyIcon&bartId=…"
}
]
}
#expressionsGet · Link to this method
POST
/expressions/upload
Upload your buddy icon
aimsid
The body is the raw image bytes (GIF, JPEG or PNG), not a form. Up to 64 KB. Your contacts get it through a presence event.
Parameters
Name Description
aimsid
string
required
Session id from startSession.
type
string
required
Always buddyIcon.
buddyIcon
f
string
Response format: json (default), xml or amf3. Add c=name for JSONP.
jsonxmlamf3
Request body: the image bytes (image/png, image/jpeg, image/gif).
Errors
460 Missing type.
462 Empty, over 64 KB, or unknown type.
Example request
cURL
JavaScript
Python
Copy
curl -X POST "https://jimm.online/webapi/expressions/upload?aimsid=$AIMSID&type=buddyIcon&f=json" \
-H "Content-Type: image/png" \
--data-binary @avatar.png
Copy
const params = new URLSearchParams({ aimsid, type: "buddyIcon", f: "json" });
const res = await fetch(`https://jimm.online/webapi/expressions/upload?${params}`, {
method: 'POST',
body: file, // a File or Blob, up to 64 KB
});
const { response } = await res.json();
Copy
import requests
with open("avatar.png", "rb") as f:
r = requests.post("https://jimm.online/webapi/expressions/upload", params={"aimsid": aimsid, "type": "buddyIcon", "f": "json"}, data=f.read())
print(r.json()["response"])
Response What response.data holds
{
"id": "0001a1b2c3d4e5f6…"
}
#expressionsUpload · Link to this method
Events
What fetchEvents delivers
Each event looks like {type, seqNum, timestamp, eventData}. Subscribe with the events parameter of startSession.
im
An incoming message. message may carry HTML from desktop clients (<HTML><BODY>…); strip tags if you render text.
{
"type": "im",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"source": {
"aimId": "987654321",
"displayId": "987654321",
"friendly": "Вася",
"userType": "icq",
"state": "online"
},
"message": "Привет! Как дела?",
"msgId": "9c2e41d07a3b55f1",
"timestamp": 1761130042,
"imf": "plain",
"autoresponse": false
}
}
offlineIM
A message sent while you were away; timestamp is when it was sent. Deleted from the server once delivered, so it never comes twice.
{
"type": "offlineIM",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"aimId": "987654321",
"friendly": "Вася",
"message": "Ты где?",
"msgId": "3e1f…",
"timestamp": 1761100000,
"imf": "plain",
"autoresponse": false
}
}
sentIM
A copy of a message you sent, for your other sessions — sync across devices. iSent: true means this very session sent it; don’t show it twice.
{
"type": "sentIM",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"sender": {
"aimId": "123456789"
},
"dest": {
"aimId": "987654321",
"displayId": "987654321"
},
"message": "Привет!",
"msgId": "5f1c0e2a-…",
"timestamp": 1761130050,
"iSent": true
}
}
typing
The other side is typing (typing), paused (typed) or cleared (none).
{
"type": "typing",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"aimId": "987654321",
"typingStatus": "typing"
}
}
presence
A buddy changed status, x-status or icon. Only changed fields come; an empty state means unchanged — don’t mark them offline.
{
"type": "presence",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"aimId": "987654321",
"friendly": "Вася",
"state": "away",
"statusMsg": "обедаю",
"userType": "icq",
"moodIcon": "https://jimm.online/webapi/…",
"onlineTime": 1761120000
}
}
buddylist
The whole buddy list, at sign-in and after any change. Replace your list with it, don’t merge.
{
"type": "buddylist",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"groups": [
{
"name": "Друзья",
"id": 1,
"buddies": [
{
"aimId": "987654321",
"displayId": "987654321",
"friendly": "Вася",
"state": "online",
"statusMsg": "на связи",
"onlineTime": 1761120000,
"userType": "icq",
"service": "icq",
"buddyIcon": "https://jimm.online/webapi/expressions/get?t=987654321&type=buddyIcon",
"bot": false
}
]
}
]
}
}
myInfo
Your own status and info, at sign-in and on change.
{
"type": "myInfo",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"aimId": "123456789",
"displayId": "123456789",
"state": "online",
"userType": "icq",
"statusMsg": "",
"capabilities": []
}
}
preference
Server preferences: at sign-in and after preference/set.
{
"type": "preference",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"showGroups": 1,
"acceptOffLineIM": 1
}
}
permitDeny
Privacy mode and block lists: at sign-in and on change.
{
"type": "permitDeny",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"pdMode": "permitAll"
}
}
rateLimit
You are sending too fast: warn, limit (messages refused), clear (go ahead).
{
"type": "rateLimit",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"classes": [
{
"id": 3,
"status": "limit"
}
]
}
}
clientError
The recipient’s client could not handle your message; cookie is the msgId from sendIM.
{
"type": "clientError",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {
"source": {
"aimId": "987654321"
},
"cookie": "5f1c0e2a-…",
"channel": "im"
}
}
sessionEnded
The server closed the session (rate limits or a restart, say). Stop polling and sign in again.
{
"type": "sessionEnded",
"seqNum": 12,
"timestamp": 1761130042,
"eventData": {}
}
statusCode values
Code HTTP Meaning
200
200
Success.
330
401
Sign in again. With statusDetailCode: 3011, wrong password.
400
400
A parameter is missing or wrong; see statusText.
401
401 / 200
Token or aimsid no longer valid: the session is closed or expired.
430
200
Rate limited. Wait the seconds in the Retry-After header.
460
400
A required parameter is missing.
462
400
A parameter is present but unusable.
602
200
Message not delivered: recipient offline, box full, or blocked.
Presence states
online
Online
away
Away
idle
Idle (hasn’t touched the client for a while). Set by the server, not by you.
dnd
Do not disturb
occupied
Occupied
invisible
Invisible — how you see yourself; others see `offline`.
offline
Offline
X-statuses (mood)
Codes for presence/setStatus?mood=….
0icqmood0
Shopping
0icqmood1
Bathing
0icqmood2
Tired
0icqmood3
Party
0icqmood4
Beer
0icqmood5
Thinking
0icqmood6
Eating
0icqmood7
TV
0icqmood8
Friends
0icqmood9
Coffee
0icqmood10
Music
0icqmood11
Business
0icqmood12
Cinema
0icqmood13
Having fun
0icqmood14
Phone
0icqmood15
PSP
0icqmood16
Studying
0icqmood17
Sick
0icqmood18
Falling asleep
0icqmood19
Surfing
0icqmood20
Internet
0icqmood21
Working
0icqmood22
Typing
0icqmood23
Angry
0icqmood61
Love
0icqmood66
Weekend
0icqmood68
WC
0icqmood70
Sleeping
0icqmood71
On mobile
0icqmood76
In love
0icqmood77
Confused
0icqmood81
Gaming
0icqmood83
On the way
0icqmood84
Diary
0icqmood85
Searching
OpenAPI spec
The whole API in one file: import it into Postman or Insomnia, open it in Swagger Editor, or generate an SDK for your language.
The server is open-oscar-server by mk6i, an MIT-licensed open project. The API is compatible with AOL’s Web AIM API, so the old AOL docs help in places too.
Spotted a mistake or missing a method? Tell us in the Telegram community . Built a client? Show us — we’ll write about it on the blog.