TypeScript SDK for the Mosir public GraphQL API.
- generated TypeScript types from
public.graphqls - generated operation wrappers from
public.operations.graphql - optional Bearer token auth
- default endpoint:
https://beta.mosir.app/api/v1 - SSE subscription support out of the box
- raw GraphQL access for developers who want direct control
- dual package output: ESM + CJS
This SDK uses:
graphql-requestfor queries and mutationsgraphql-ssefor subscriptions
This keeps the package small while still supporting the preferred subscription transport. WebSocket support is intentionally not bundled. If you want WebSocket subscriptions, use your own GraphQL/WebSocket client with the exported generated documents and types.
npm install mosir-sdk-tsor:
pnpm add mosir-sdk-ts
# or
yarn add mosir-sdk-ts
# or
bun add mosir-sdk-tsOnly public data needs no token.
import { createMosirClient } from 'mosir-sdk-ts'
const client = createMosirClient({})
const post = await client.getPost({ postId: 'VLO8u7UXqclQ7byjfMEX0' })
console.log(post.getPost?.content)Use a token for authenticated operations such as notifications.
import { createMosirClient } from 'mosir-sdk-ts'
const client = createMosirClient({
token: process.env.MOSIR_API_TOKEN,
})
const notifications = await client.getNotifications({ limit: 20 })
console.log(notifications.getNotifications.edges)import { createMosirClient } from 'mosir-sdk-ts'
const client = createMosirClient({
token: process.env.MOSIR_API_TOKEN,
endpoint: 'https://example.com/api/v1',
})Both the generated PascalCase names and SDK-friendly camelCase aliases are available, but camelCase is preferred.
const client = createMosirClient({})
const post = await client.getPost({ postId: 'VLO8u7UXqclQ7byjfMEX0' })
console.log(post.getPost?.author.username)
console.log(post.getPost?.content)Replies are exposed as nested GraphQL fields on Post, so this is a good case for direct GraphQL usage:
const client = createMosirClient({})
const replies = await client.request(
/* GraphQL */ `
query GetPostReplies($postId: ID!, $limit: Int) {
getPost(postId: $postId) {
id
commentsRecent(limit: $limit) {
edges {
id
content
createdAt
author {
id
username
displayName
}
}
pageInfo {
endCursor
hasNextPage
totalCount
}
}
}
}
`,
{
postId: 'VLO8u7UXqclQ7byjfMEX0',
limit: 3,
},
)
console.log(replies.getPost?.commentsRecent.edges)
// one reply in this thread is: 47awwiLrfk5snCOxFFoXGconst client = createMosirClient({
token: process.env.MOSIR_API_TOKEN,
})
const notifications = await client.getNotifications({ limit: 20 })
console.log(notifications.getNotifications.edges)const client = createMosirClient({})
const post = await client.getPost({ postId: 'VLO8u7UXqclQ7byjfMEX0' })
const media = post.getPost?.attachments[0]?.media
if (media) {
const response = await client.fetchMedia(media)
const bytes = await response.arrayBuffer()
console.log(bytes.byteLength)
}const client = createMosirClient({})
const previewUrl = client.getPreviewImageUrl('post', 'VLO8u7UXqclQ7byjfMEX0')
console.log(previewUrl)
const previewResponse = await client.fetchPreviewImage('post', 'VLO8u7UXqclQ7byjfMEX0')
const previewBytes = await previewResponse.arrayBuffer()
console.log(previewBytes.byteLength)The same generated methods are also available under client.sdk:
const account = await client.sdk.getCurrentAccount()Subscriptions let your app receive updates from Mosir in near real time without polling. This SDK uses SSE (Server-Sent Events) for subscriptions by default.
A good example is a Discord bot:
- subscribe to
postCreatedByAuthor - when a creator publishes something new, format it
- send a message into a Discord channel
That way the bot reacts as soon as something changes, instead of repeatedly calling the API every few seconds.
SSE is especially useful for backend workers, bots, notification relays, and other long-running processes that want a simple one-way stream of events from the server.
For public subscriptions like postCreatedByAuthor, a token is not required.
Note: each SSE connection lasts at most 1 hour. In practice, network conditions may cause it to end earlier. If you build a bot, worker, or relay process, make sure you implement reconnect logic.
const client = createMosirClient({})
const profile = await client.getAccountProfile({ username: 'leemiyinghao' })
const authorId = profile.getAccountProfile.id
for await (const event of client.postCreatedByAuthor({
authorId,
postType: 'POST',
})) {
console.log(event.postCreatedByAuthor.id)
console.log(event.postCreatedByAuthor.content)
}You can also use the lower-level raw subscription API:
import { PostCreatedByAuthorDocument } from 'mosir-sdk-ts'
const client = createMosirClient({})
const profile = await client.getAccountProfile({ username: 'leemiyinghao' })
const authorId = profile.getAccountProfile.id
for await (const event of client.subscribe(PostCreatedByAuthorDocument, {
authorId,
postType: 'POST',
})) {
console.log(event.postCreatedByAuthor.content)
}Authentication is optional. Pass token for authenticated operations, or omit it when accessing only public data.
import { createMosirClient, GetNotificationsDocument } from 'mosir-sdk-ts'
const client = createMosirClient({
token: process.env.MOSIR_API_TOKEN,
})
const data = await client.request(GetNotificationsDocument, {
limit: 20,
})Example real public post lookup against https://beta.mosir.app/api/v1:
const post = await client.getPost({ postId: 'VLO8u7UXqclQ7byjfMEX0' })
console.log(post.getPost)
// {
// id: 'VLO8u7UXqclQ7byjfMEX0',
// content: '**重力感應自動導航***(實驗性)*\n您現在可以不用手滑mosir。(手機限定)',
// createdAt: '2026-03-31T16:01:24Z',
// author: {
// id: 'GBWfRinN_Ya65D3SJaNS4',
// username: 'leemiyinghao',
// displayName: 'catLee'
// },
// ...
// }const replies = await client.request(
/* GraphQL */ `
query GetPostReplies($postId: ID!, $limit: Int) {
getPost(postId: $postId) {
id
commentsRecent(limit: $limit) {
edges {
id
content
createdAt
author {
username
displayName
}
}
}
}
}
`,
{
postId: 'VLO8u7UXqclQ7byjfMEX0',
limit: 3,
},
)WebSocket transport is not bundled. If you want it, use your own GraphQL WebSocket client against the same endpoint and reuse the exported generated documents and types from this package.
- default endpoint:
https://beta.mosir.app/api/v1 tokenis optional for public data and required only for authenticated operations- the same applies to subscriptions: public subscription data does not require a token
- media helpers are available through
selectMediaFile(...)andfetchMedia(...) - preview image helpers are available through
getPreviewImageUrl(...)andfetchPreviewImage(...) - subscriptions use SSE in this SDK
- direct GraphQL usage is supported through exported typed documents and
client.request(...)/client.subscribe(...)
task installtask codegentask typechecktask buildtask checkpublic.graphqls— copied public schema artifactpublic.operations.graphql— copied curated operation documentsrc/generated/graphql.ts— generated GraphQL types and typed documentssrc/generated/sdk.ts— generated operation wrapper methods
This project is licensed under the GNU Lesser General Public License v3.0 (LGPL-3.0).
See LICENSE for details.