API Documentation
Get started with Rnote API — from sign-up to your first request.
Base URL
https://rnote.dev/api/v2/crawler
All API endpoints use this prefix. The full interactive reference is available via Swagger UI.
Online API playground
We provide an Apifox-based online playground — enter your API key and test every endpoint right in the browser, no code required.
Open the playgroundBefore you start
- 1 Create an account and verify your email
- 2 Sign in to the admin panel and create an API key under "API Keys"
- 3 Top up your balance on the Billing page (only successful requests are charged)
Authentication
All API requests authenticate by passing your API key in the X-API-Key header.
# Pass your API key in an HTTP header
curl -X 'GET' \
'https://rnote.dev/api/v2/crawler/note/image?note_id=697c0eee000000000a03c308' \
-H 'accept: application/json' \
-H 'X-API-Key: sk-5bc4****************************e175'
Your First Request
Example — fetching an image note's detail:
curl -X 'GET' \
'https://rnote.dev/api/v2/crawler/note/image?note_id=697c0eee000000000a03c308' \
-H 'accept: application/json' \
-H 'X-API-Key: sk-5bc4****************************e175'
import requests
API_KEY = "sk-5bc4****************************e175"
BASE_URL = "https://rnote.dev/api/v2/crawler"
response = requests.get(
f"{BASE_URL}/note/image",
params={"note_id": "697c0eee000000000a03c308"},
headers={
"X-API-Key": API_KEY,
"accept": "application/json",
},
)
data = response.json()
print(data)
const API_KEY = "sk-5bc4****************************e175";
const BASE_URL = "https://rnote.dev/api/v2/crawler";
const res = await fetch(
`${BASE_URL}/note/image?note_id=697c0eee000000000a03c308`,
{
headers: {
"X-API-Key": API_KEY,
"accept": "application/json",
},
}
);
const data = await res.json();
console.log(data);
Note APIs
/note/image
Fetch an image note's detail — content, image list, author info, engagement metrics and more.
note_id (required)
/note/video
Fetch a video note's detail — playback URL, cover image, author info and more.
note_id (required)
/note/mixed
Fetch home-feed recommendation notes; leave note_id empty to return the recommendation feed.
note_id (optional)
/note/comments
Fetch a note's comments, with pagination and multiple sort options.
note_id (required) · cursor · index · sort_strategy (default / latest_v2 / like_count)
/note/sub_comments
Fetch second-level comments (replies) on a note, with cursor pagination.
note_id (required) · comment_id (required) · cursor · index · num
/note/metrics
Report note metrics (likes, collects, shares and other engagement data).
note_id · report_type · target_count
User APIs
/user/info
Fetch a user's profile — nickname, avatar, bio, follower count and more.
user_id (required)
/user/posted
Fetch the notes a user has posted, with cursor pagination.
user_id (required) · cursor · num
/user/faved
Fetch the notes a user has collected, with cursor pagination.
user_id (required) · cursor · num
Search APIs
/search/notes
Search notes, with sorting and filtering.
keyword (required) · page · sort (general / time_descending / popularity_descending) · note_type (0=all / 1=video / 2=image)
/search/users
Search users.
keyword (required) · page
/search/images
Search images.
keyword (required) · page
/search/products
Search products.
keyword (required) · page · sort_by · source
/search/groups
Search group chats.
keyword (required) · page
Product APIs
/product/detail
Fetch product detail.
product_id (required)
/product/review/overview
Fetch a product's review summary.
product_id (required)
/product/reviews
Fetch a product's reviews, with cursor pagination.
product_id (required) · cursor · sort_type
/product/recommendations
Fetch related-product recommendations.
product_id (required) · cursor
Topic APIs
/topic/info
Fetch topic detail.
topic_id (required)
/topic/feed
Fetch notes under a topic, with cursor pagination.
topic_id (required) · cursor · sort_by
Creator Insights
/creator/inspiration/feed
Fetch recommended creator inspirations.
cursor · num
/creator/hot/inspiration/feed
Fetch trending creator inspirations.
cursor · num
Response Format
All data endpoints (/api/v2/crawler/*, /api/v2/pgy/*) use a consistent JSON envelope:
Successful response
{
"success": true,
"data": { /* Business data, shape varies by endpoint */ },
"billed": true,
"debug_id": "a1b2c3d4",
"debug_info": "..." /* diagnostic info — include it when reporting an issue */
}
Failure response
{
"success": false,
"data": null,
"error": "Rate limited, please retry later",
"retry_after": 5.0,
"billed": false,
"debug_id": "a1b2c3d4",
"debug_info": "..." /* diagnostic info — include it when reporting an issue */
}
Field reference
| Field | Type | Description |
|---|---|---|
success |
bool | Business success flag (matches HTTP status semantics) |
data |
object | null | Business data; null on failure |
error |
string | null | Generic error message; null on success |
retry_after |
float | null | Suggested wait seconds on rate-limit / temporary unavailability; mirrors the HTTP Retry-After header |
billed |
bool | Whether this request was billed (only successful requests are billed; any failure is free) |
debug_id |
string | null | 8-character random correlation code; include it when reporting an issue so we can locate this request |
debug_info |
string | null | Diagnostic info; include it when reporting an issue (no need to decode it) |
About debug_id and debug_info
When reporting an issue, including the debug_id (short code) or debug_info from the response helps us locate the request much faster. You don't need to decode them — just send them to us as-is.
Error Codes
Middleware layer (auth / rate-limit / billing)
These statuses are returned before the request reaches business logic, regardless of endpoint.
| HTTP status | Meaning | How to handle |
|---|---|---|
401 |
Missing or invalid API key | Check the X-API-Key header |
402 |
Insufficient balance | Top up your balance in the admin panel |
403 |
Not authorized for this endpoint | Check your API key's scopes |
429 |
Per-user / per-IP rate limit exceeded | Reduce your request rate and retry later |
Business layer (data endpoints)
Data endpoints use standard 4xx/5xx HTTP status codes on failure, plus a Retry-After header where relevant. Check both the HTTP status and body.success.
| HTTP status | Trigger | How to handle |
|---|---|---|
400 |
Invalid request parameter | Fix the parameter (do not retry) |
404 |
Endpoint does not exist | Check the URL path |
429 |
Too many requests | Wait the duration in the Retry-After header, then retry |
500 |
Internal server error | Retry later; if it persists, contact support with the debug_id |
502 |
Data source temporarily refused or unavailable | Retry later (changing parameters usually doesn't help) |
503 |
Service temporarily busy | Wait the duration in the Retry-After header, then retry |
504 |
Request pipeline timeout | Retry later |
Client error-handling example
Recommended pattern — check both HTTP status and body.success, and include debug_id in your error logs:
import requests
resp = requests.get(
"https://rnote.dev/api/v2/crawler/user/info",
headers={"X-API-Key": "sk-..."},
params={"user_id": "..."},
timeout=20,
)
body = resp.json()
# Double-check: HTTP status first, body.success fallback
if resp.status_code >= 400 or not body.get("success"):
error = body.get("error", "Unknown error")
debug_id = body.get("debug_id", "n/a")
retry_after = body.get("retry_after")
print(f"Request failed [{debug_id}]: {error}", end="")
if retry_after:
print(f" (retry in {retry_after}s)")
# Include debug_id when contacting support
else:
data = body["data"]
# Process business data ...
Billing
Per-request billing
Only successful (HTTP 2xx) requests are billed; failed requests are free. Each endpoint is priced independently.
Insufficient balance
When your balance can't cover a request, the API returns HTTP 402 and the request is not executed.
Transaction records
Every charge is viewable on the Billing page of the admin panel — time, endpoint, amount and more.