API
Authorization
GET /auth/{provider}/login?from=http://url&site=site_id&session=1
- perform "social" login with one of supported providers and redirect tourl
. The presence ofsession
(any non-zero value) change the default cookie expiration and makes them session-onlyGET /auth/logout
- logout
type User struct {
Name string `json:"name"`
ID string `json:"id"`
Picture string `json:"picture"`
Admin bool `json:"admin"`
Blocked bool `json:"block"`
Verified bool `json:"verified"`
PaidSub bool `json:"paid_sub"` // is paid Patreon subscriber
}
Commenting
POST /api/v1/comment
- add a comment, auth required
type Comment struct {
ID string `json:"id"` // comment ID, read only
ParentID string `json:"pid"` // parent ID
Text string `json:"text"` // comment text, after md processing
Orig string `json:"orig"` // original comment text in Markdown, should never be rendered as HTML as-is!
User User `json:"user"` // user info, read only
Locator Locator `json:"locator"` // post locator
Score int `json:"score"` // comment score, read only
Vote int `json:"vote"` // vote for the current user, -1/1/0
Controversy float64 `json:"controversy,omitempty"` // comment controversy, read only
Timestamp time.Time `json:"time"` // time stamp, read only
Edit *Edit `json:"edit,omitempty" bson:"edit,omitempty"` // pointer to have empty default in JSON response
Pin bool `json:"pin"` // pinned status, read only
Delete bool `json:"delete"` // delete status, read only
PostTitle string `json:"title"` // post title
}
type Locator struct {
SiteID string `json:"site"` // site ID
URL string `json:"url"` // post URL
}
type Edit struct {
Timestamp time.Time `json:"time" bson:"time"`
Summary string `json:"summary"`
}
POST /api/v1/preview
- preview comment in HTML. Body isComment
to renderGET /api/v1/find?site=site-id&url=post-url&sort=fld&format=tree|plain
- find all comments for given post
This is the primary call UI uses to show comments for the given post. It can return comments in two formats - plain
and tree
. In plain format, the result will be a sorted list of Comment
. In tree format, this is going to be a tree-like object with this structure:
type Tree struct {
Nodes []Node `json:"comments"`
Info store.PostInfo `json:"info,omitempty"`
}
type Node struct {
Comment store.Comment `json:"comment"`
Replies []Node `json:"replies,omitempty"`
}
Sort can be time
, active
, or score
. Supported sort order with prefix -/+, i.e., -time
. For tree
mode, the sort will be applied to top-level comments only, and all replies are always sorted by time.
PUT /api/v1/comment/{id}?site=site-id&url=post-url
- edit comment, allowed once inEDIT_TIME
minutes since creation. Body isEditRequest
JSON
type EditRequest struct {
Text string `json:"text"` // updated text
Summary string `json:"summary"` // optional, summary of the edit
Delete bool `json:"delete"` // delete flag
}{}
GET /api/v1/last/{max}?site=site-id&since=ts-msec
- get up to{max}
last comments,since
(epoch time, milliseconds) is optionalGET /api/v1/id/{id}?site=site-id
- get comment bycomment id
GET /api/v1/comments?site=site-id&user=id&limit=N
- get comment byuser id
, returnsresponse
object.
Important: original comment text in Markdown in the orig
field should never be rendered as HTML as-is, only text
containing HTML is sanitized and safe for render.
type response struct {
Comments []store.Comment `json:"comments"`
Count int `json:"count"`
}{}
GET /api/v1/count?site=site-id&url=post-url
- get comment's count for{url}
POST /api/v1/count?site=siteID
- get number of comments for posts from post body (list of post IDs)GET /api/v1/list?site=site-id&limit=5&skip=2
- list commented posts, returns array orPostInfo
, limit=0 will return all posts
type PostInfo struct {
URL string `json:"url"`
Count int `json:"count"`
ReadOnly bool `json:"read_only,omitempty"`
FirstTS time.Time `json:"first_time,omitempty"`
LastTS time.Time `json:"last_time,omitempty"`
}
GET /api/v1/user
- get user info, auth requiredPUT /api/v1/vote/{id}?site=site-id&url=post-url&vote=1
- vote for comment.vote
=1 will increase score, -1 decrease, auth requiredGET /api/v1/userdata?site=site-id
- export all user data to gz stream, auth requiredPOST /api/v1/deleteme?site=site-id
- request deletion of user data, auth requiredGET /api/v1/config?site=site-id
- returns configuration (parameters) for given site
type Config struct {
Version string `json:"version"`
EditDuration int `json:"edit_duration"`
MaxCommentSize int `json:"max_comment_size"`
Admins []string `json:"admins"`
AdminEmail string `json:"admin_email"`
Auth []string `json:"auth_providers"`
LowScore int `json:"low_score"`
CriticalScore int `json:"critical_score"`
PositiveScore bool `json:"positive_score"`
ReadOnlyAge int `json:"readonly_age"`
MaxImageSize int `json:"max_image_size"`
EmojiEnabled bool `json:"emoji_enabled"`
SubscribersOnly bool `json:"subscribers_only"` // enable commenting only for Patreon subscribers
}
GET /api/v1/info?site=site-idd&url=post-url
- returnsPostInfo
for site and URL
Streaming API
Not available
Streaming API supposed to provide server-sent events for post updates as well as a site update:GET /api/v1/stream/info?site=site-idd&url=post-url&since=unix_ts_msec
- returns stream (event: info
) withPostInfo
records for the site and URL.since
is optionalGET /api/v1/stream/last?site=site-id&since=unix_ts_msec
- returns updates stream (event: last
) with comments for the site,since
is optional
It was removed in https://github.com/umputun/remark42/pull/826 due to not being used and affecting tests flakiness and could be returned if there will be a developer who would be willing to write frontend support for it.
Response example
data: {"url":"https://radio-t.com/blah1","count":2,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.142872-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":3,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.157709-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":4,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.172991-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":5,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.188429-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":6,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.204742-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":7,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.220692-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":8,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.23817-05:00"}
event: info
data: {"url":"https://radio-t.com/blah1","count":9,"first_time":"2019-06-18T12:53:48.125686-05:00","last_time":"2019-06-18T12:53:48.254669-05:00"}
RSS Feeds
GET /api/v1/rss/post?site=site-id&url=post-url
- RSS feed for a postGET /api/v1/rss/site?site=site-id
- RSS feed for given siteGET /api/v1/rss/reply?site=site-id&user=user-id
- RSS feed for replies to user's comments
Images Management
GET /api/v1/picture/{user}/{id}
- load stored imagePOST /api/v1/picture
- upload and store image, uses post form withFormFile("file")
. Returns{"id": user/imgid}
, auth required
returned ID should be appended to load image URL on the caller side
Email Subscription
GET /api/v1/email?site=site-id
- get user's email, auth requiredPOST /api/v1/email/subscribe?site=site-id&address=user@example.org
- makes confirmation token and sends it to the user over email, auth requiredTrying to subscribe to the same email a second time will return response code
409 Conflict
with explaining error messagePOST /api/v1/email/confirm?site=site-id&tkn=token
- uses provided token parameter to set email for the user, auth requiredSetting email subscribe user for all first-level replies to his messages
DELETE /api/v1/email?site=siteID
- removes user's email, auth required
Admin
DELETE /api/v1/admin/comment/{id}?site=site-id&url=post-url
- delete comment byid
PUT /api/v1/admin/user/{userid}?site=site-id&block=1&ttl=7d
- block or unblock user with optional TTL (default=permanent)GET api/v1/admin/blocked&site=site-id
- list of blocked user IDs
type BlockedUser struct {
ID string `json:"id"`
Name string `json:"name"`
Until time.Time `json:"time"`
}
GET /api/v1/admin/export?site=site-id&mode=[stream|file]
- export all comments to JSON stream or gz filePOST /api/v1/admin/import?site=site-id
- import comments from the backup, uses post bodyPOST /api/v1/admin/import/form?site=site-id
- import comments from the backup, user post formPOST /api/v1/admin/remap?site=site-id
- remap comments to different URLs. Expect a list of "from-url new-url" pairs separated by \n. From-url and new-url parts are separated by space. If URLs end with an asterisk (*), it means matching the prefix. Remap procedure based on export/import chain so make the backup first
http://oldsite.com* https://newsite.com*
http://oldsite.com/from-old-page/1 https://newsite.com/to-new-page/1
GET /api/v1/admin/wait?site=site-id
- wait for completion for any async migration ops (import or remap)PUT /api/v1/admin/pin/{id}?site=site-id&url=post-url&pin=1
- pin or unpin commentGET /api/v1/admin/user/{userid}?site=site-id
- get user's infoDELETE /api/v1/admin/user/{userid}?site=site-id
- delete all user's commentsPUT /api/v1/admin/readonly?site=site-id&url=post-url&ro=1
- set read-only statusPUT /api/v1/admin/verify/{userid}?site=site-id&verified=1
- set verified statusGET /api/v1/admin/deleteme?token=token
- process deleteme user's request
all admin calls require auth and admin privilege