Media
Avatars (profile pictures) and custom emotes
The Media API handles profile pictures (avatars) and custom emotes with thumbnail generation.
Avatars
Avatar Sizes
| Size | Description |
|---|---|
cropped |
Full cropped version |
1600 |
Large thumbnail |
512 |
Medium thumbnail |
256 |
Default size |
128 |
Small thumbnail |
64 |
Icon size |
Get User Avatar
Get the avatar URL for any user (public endpoint).
GET /v1/users/{userID}/avatar?size=256
Query Parameters:
| Param | Default | Description |
|---|---|---|
size |
256 | Thumbnail size |
Response:
{
"url": "https://cdn.ocvr.net/...",
"expires_at": 1703533600
}
Error Codes:
| Code | Description |
|---|---|
AVATAR_NOT_FOUND |
User has no avatar |
AVATAR_NOT_READY |
Still processing |
INVALID_SIZE |
Invalid size parameter |
Set Avatar
Set your profile picture from an uploaded file.
PUT /v1/users/me/avatar
Authorization: Bearer {token}
{
"file_id": "999888777"
}
Response: 204 No Content
Notes:
- The file must be a
profile_picasset type - The file must be in
readyprocessing state - Upload via Uploads API first
Error Codes:
| Code | Description |
|---|---|
FILE_NOT_FOUND |
File doesn't exist |
FILE_NOT_PROFILE_PIC |
Not a profile_pic asset |
FILE_NOT_READY |
Still processing |
Remove Avatar
Remove your profile picture.
DELETE /v1/users/me/avatar
Authorization: Bearer {token}
Response: 204 No Content
Notes:
- The profile_pic file is not deleted
- You can reassign it later
Re-crop Avatar
Re-crop your avatar with different coordinates.
POST /v1/users/me/avatar/recrop
Authorization: Bearer {token}
{
"crop_x": 100,
"crop_y": 50,
"crop_w": 400,
"crop_h": 400
}
Response (202 Accepted):
{
"status": "processing",
"message": "Avatar recrop queued"
}
Notes:
- Queues a processing job to regenerate thumbnails
- Avatar will be temporarily unavailable during processing
- Poll the avatar endpoint until ready
Error Codes:
| Code | Description |
|---|---|
AVATAR_NOT_FOUND |
No avatar to recrop |
RECROP_INVALID |
Invalid crop parameters |
Emotes
Emote Sizes
| Size | Description |
|---|---|
full |
Original size |
256 |
Large thumbnail |
128 |
Default size |
64 |
Small size |
List Emotes
List your custom emotes.
GET /v1/emotes?limit=100&cursor={cursor}
Authorization: Bearer {token}
Query Parameters:
| Param | Default | Description |
|---|---|---|
limit |
100 | Max results (1-500) |
cursor |
- | Pagination cursor |
Response:
{
"emotes": [
{
"id": "111222333",
"owner_id": "12345",
"name": "cool_emote.gif",
"shortcode": "cool",
"size_bytes": 262144,
"mime_type": "image/gif",
"processing_state": "ready",
"created_at": 1703520000,
"updated_at": 1703520000
}
],
"next_cursor": null
}
Get Emote
Get emote details.
GET /v1/emotes/{emoteID}
Authorization: Bearer {token}
Response:
{
"id": "111222333",
"owner_id": "12345",
"name": "cool_emote.gif",
"shortcode": "cool",
"size_bytes": 262144,
"mime_type": "image/gif",
"processing_state": "ready",
"created_at": 1703520000,
"updated_at": 1703520000
}
Get Emote URL
Get presigned URL for an emote.
GET /v1/emotes/{emoteID}/url?size=128
Authorization: Bearer {token}
Query Parameters:
| Param | Default | Description |
|---|---|---|
size |
128 | Thumbnail size (full, 256, 128, 64) |
Response:
{
"url": "https://cdn.ocvr.net/...",
"expires_at": 1703533600
}
Access:
- Owner can always access their emotes
- Public emotes can be accessed by anyone
Error Codes:
| Code | Description |
|---|---|
EMOTE_NOT_FOUND |
Emote doesn't exist |
EMOTE_NOT_READY |
Still processing |
INVALID_SIZE |
Invalid size parameter |
Update Emote
Update emote shortcode.
PUT /v1/emotes/{emoteID}
Authorization: Bearer {token}
{
"shortcode": "new_shortcode"
}
Response:
{
"id": "111222333",
"owner_id": "12345",
"name": "cool_emote.gif",
"shortcode": "new_shortcode",
"size_bytes": 262144,
"mime_type": "image/gif",
"processing_state": "ready",
"created_at": 1703520000,
"updated_at": 1703535000
}
Shortcode Rules:
- 2-32 characters
- Letters, numbers, and underscores only
Error Codes:
| Code | Description |
|---|---|
EMOTE_NOT_OWNER |
Not your emote |
SHORTCODE_INVALID |
Invalid shortcode format |
Delete Emote
Delete an emote.
DELETE /v1/emotes/{emoteID}
Authorization: Bearer {token}
Response: 204 No Content
Notes:
- Soft delete (moves to trash)
- Quota is freed immediately
Using Emotes in Chat
Emotes can be used in chat messages via the inline_emotes field:
{
"body": "Hello :cool: world!",
"inline_emotes": [
{
"shortcode": "cool",
"asset_id": 111222333,
"start_index": 6,
"end_index": 12
}
]
}
The client should replace :shortcode: patterns with the emote image when rendering.
Uploading Avatars and Emotes
Use the Uploads API:
Profile Picture:
{
"upload_type": "profile_pic",
"filename": "avatar.png",
"content_type": "image/png",
"size_bytes": 524288,
"crop_x": 0,
"crop_y": 0,
"crop_w": 512,
"crop_h": 512
}
Emote:
{
"upload_type": "emote",
"filename": "reaction.gif",
"content_type": "image/gif",
"size_bytes": 102400,
"shortcode": "reaction"
}