January 1, 2025
API Reference
Rox provides a Misskey-compatible API for seamless integration with existing Misskey clients.
Base URL
https://api.your-domain.com
Authentication
Create Account
POST /api/signup
Content-Type: application/json
{
"username": "alice",
"password": "secure_password"
}
Response:
{
"id": "user_123",
"username": "alice",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Login
POST /api/signin
Content-Type: application/json
{
"username": "alice",
"password": "secure_password"
}
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "user_123",
"username": "alice",
"displayName": "Alice"
}
}
Using Tokens
Include the token in the Authorization header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Notes (Posts)
Create Note
POST /api/notes/create
Authorization: Bearer {token}
Content-Type: application/json
{
"text": "Hello, Fediverse!",
"visibility": "public",
"fileIds": ["file_123"],
"cw": "Content warning text (optional)",
"replyId": "note_456 (optional)",
"renoteId": "note_789 (optional)"
}
Parameters:
text(string): Note contentvisibility(string):public,home,followers,specifiedfileIds(array): Array of uploaded file IDscw(string, optional): Content warningreplyId(string, optional): ID of note to reply torenoteId(string, optional): ID of note to renote
Response:
{
"createdNote": {
"id": "note_123",
"text": "Hello, Fediverse!",
"userId": "user_123",
"visibility": "public",
"createdAt": "2025-01-01T00:00:00.000Z"
}
}
Get Timeline
POST /api/notes/timeline
Authorization: Bearer {token}
Content-Type: application/json
{
"limit": 20,
"sinceId": "note_100",
"untilId": "note_200"
}
Parameters:
limit(number): Number of notes (max 100)sinceId(string, optional): Get notes after this IDuntilId(string, optional): Get notes before this ID
Response:
[
{
"id": "note_123",
"text": "Hello!",
"user": {
"id": "user_123",
"username": "alice",
"displayName": "Alice"
},
"createdAt": "2025-01-01T00:00:00.000Z",
"reactions": {
"👍": 5,
"❤️": 3
}
}
]
Delete Note
POST /api/notes/delete
Authorization: Bearer {token}
Content-Type: application/json
{
"noteId": "note_123"
}
React to Note
POST /api/notes/reactions/create
Authorization: Bearer {token}
Content-Type: application/json
{
"noteId": "note_123",
"reaction": "👍"
}
Remove Reaction
POST /api/notes/reactions/delete
Authorization: Bearer {token}
Content-Type: application/json
{
"noteId": "note_123"
}
Users
Get User Info
POST /api/users/show
Content-Type: application/json
{
"username": "alice"
}
Response:
{
"id": "user_123",
"username": "alice",
"displayName": "Alice",
"description": "Bio text",
"avatarUrl": "https://example.com/avatar.jpg",
"bannerUrl": "https://example.com/banner.jpg",
"followersCount": 100,
"followingCount": 50,
"notesCount": 500
}
Get Current User
POST /api/i
Authorization: Bearer {token}
Response:
{
"id": "user_123",
"username": "alice",
"displayName": "Alice",
"email": "[email protected]"
}
Update Profile
POST /api/i/update
Authorization: Bearer {token}
Content-Type: application/json
{
"displayName": "Alice Smith",
"description": "New bio",
"avatarId": "file_123",
"bannerId": "file_456"
}
Following
Follow User
POST /api/following/create
Authorization: Bearer {token}
Content-Type: application/json
{
"userId": "user_456"
}
Unfollow User
POST /api/following/delete
Authorization: Bearer {token}
Content-Type: application/json
{
"userId": "user_456"
}
Get Followers
POST /api/users/followers
Content-Type: application/json
{
"userId": "user_123",
"limit": 20
}
Get Following
POST /api/users/following
Content-Type: application/json
{
"userId": "user_123",
"limit": 20
}
Files
Upload File
POST /api/drive/files/create
Authorization: Bearer {token}
Content-Type: multipart/form-data
file: [binary data]
name: "image.jpg"
isSensitive: false
Response:
{
"id": "file_123",
"name": "image.jpg",
"type": "image/jpeg",
"md5": "abc123...",
"size": 123456,
"url": "https://example.com/files/image.jpg",
"thumbnailUrl": "https://example.com/files/thumb_image.jpg"
}
Delete File
POST /api/drive/files/delete
Authorization: Bearer {token}
Content-Type: application/json
{
"fileId": "file_123"
}
Federation (ActivityPub)
WebFinger
GET /.well-known/webfinger?resource=acct:[email protected]
Response:
{
"subject": "acct:[email protected]",
"links": [
{
"rel": "self",
"type": "application/activity+json",
"href": "https://your-domain.com/users/alice"
}
]
}
Actor (User Profile)
GET /users/alice
Accept: application/activity+json
Response:
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Person",
"id": "https://your-domain.com/users/alice",
"inbox": "https://your-domain.com/users/alice/inbox",
"outbox": "https://your-domain.com/users/alice/outbox",
"followers": "https://your-domain.com/users/alice/followers",
"following": "https://your-domain.com/users/alice/following"
}
Rate Limiting
- Default: 100 requests per 15 minutes per IP
- Authenticated: 200 requests per 15 minutes per user
Rate Limit Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000
Error Responses
400 Bad Request
{
"error": {
"message": "Invalid request",
"code": "INVALID_PARAM",
"id": "request_123"
}
}
401 Unauthorized
{
"error": {
"message": "Authentication required",
"code": "AUTHENTICATION_FAILED"
}
}
403 Forbidden
{
"error": {
"message": "Permission denied",
"code": "PERMISSION_DENIED"
}
}
404 Not Found
{
"error": {
"message": "Resource not found",
"code": "NOT_FOUND"
}
}
429 Too Many Requests
{
"error": {
"message": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED"
}
}
Webhooks
Register Webhook
POST /api/webhooks/create
Authorization: Bearer {token}
Content-Type: application/json
{
"url": "https://your-app.com/webhook",
"events": ["note", "follow", "mention"],
"secret": "webhook_secret"
}
Webhook Payload
{
"type": "note",
"data": {
"id": "note_123",
"text": "Hello!",
"userId": "user_123"
},
"timestamp": "2025-01-01T00:00:00.000Z"
}
Streaming API
WebSocket Connection
const ws = new WebSocket('wss://api.your-domain.com/streaming');
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'connect',
body: {
channel: 'homeTimeline',
token: 'your_token'
}
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('New event:', data);
};
Available Channels
homeTimeline- Home timeline updateslocalTimeline- Local timeline updatesglobalTimeline- Global timeline updatesmain- General notifications
SDK Examples
JavaScript/TypeScript
import { RoxClient } from '@rox/sdk';
const client = new RoxClient({
baseUrl: 'https://api.your-domain.com',
token: 'your_token'
});
// Create note
const note = await client.notes.create({
text: 'Hello from SDK!'
});
// Get timeline
const timeline = await client.notes.timeline({
limit: 20
});
cURL
# Create note
curl -X POST https://api.your-domain.com/api/notes/create \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"text":"Hello from cURL!"}'
Next Steps
- Authentication Guide - Detailed authentication flows
- Federation Guide - ActivityPub federation details
- Deployment Guide - Deploy your instance