SDK Reference
All symbols are importable from the bare package name. Your bundler or runtime resolves the correct entry automatically via conditional exports.
import { configureApi, getSDKInfo, SDK_NAME, SDK_VERSION, api } from '@coin-communities/sdk';For React apps, @coin-communities/sdk/react-query re-exports everything below plus pre-baked hooks. See the React Query page.
Functions
configureApi()
Configures the shared HTTP client used by all api.* functions. Call this once at
application startup — typically before any API call is made.
Signature
function configureApi(options: ConfigureApiOptions): voidParameters
options(ConfigureApiOptions, required) — seeConfigureApiOptions.
Example
import { configureApi } from '@coin-communities/sdk';
configureApi({
baseUrl: 'https://api.coin-communities.xyz',
headers: { 'x-api-key': 'YOUR_API_KEY' },
});baseUrl is the API origin. The generated client paths already include
/api/v1/..., so don't append it.
getSDKInfo()
Returns metadata describing the SDK and the runtime it was bundled for.
Signature
function getSDKInfo(): SDKInfoPlatform-divergent behaviour — the platform field reflects the conditional export resolved at bundle time.
| Runtime | platform value |
|---|---|
| Browser (React) | 'react' |
| React Native | 'react-native' |
| Node.js / default | 'node' |
Returns SDKInfo
Example
import { getSDKInfo } from '@coin-communities/sdk';
const info = getSDKInfo();
// { name: '@coin-communities/sdk', version: '0.0.8', platform: 'react' }Authentication
The API uses two authentication schemes. Configure the right one via configureApi.
API key (x-api-key)
Most read and write operations on communities, users, and the feed accept an API key
sent as the x-api-key request header. Create a key in the business dashboard or via
api.createApiKey().
configureApi({
baseUrl: 'https://api.coin-communities.xyz',
headers: { 'x-api-key': process.env.CC_API_KEY },
});Bearer JWT (Authorization: Bearer)
Business management operations (API keys, members, callbacks, audit logs) require a JWT
obtained by calling api.login() with business email + password credentials.
configureApi({
baseUrl: 'https://api.coin-communities.xyz',
auth: () => sessionStorage.getItem('token') ?? '',
});Set auth to a function returning the JWT string. It is called per-request and may be
async. If you need both schemes simultaneously, put the API key in headers and the
JWT in auth.
Server key + secret (x-server-key / x-server-secret)
The *Server operations (see Community — Server-side operations)
authenticate with a server API key pair rather than an API key or JWT. Both headers
are required and must never be shipped to a browser. Mint a pair with api.createServerApiKey().
configureApi({
baseUrl: 'https://api.coin-communities.xyz',
headers: {
'x-server-key': process.env.CC_SERVER_KEY,
'x-server-secret': process.env.CC_SERVER_SECRET,
},
});Unauthenticated endpoints
Only the platform health probes require no authentication:
| Endpoint | Description |
|---|---|
GET /health | Liveness check |
GET /ping | Latency probe |
The */public operations (getTopCommunities, getMessagesPublic, getFeedPublic)
read data anonymously — they don't need a user JWT — but they still require an
x-api-key. Pass it via configureApi({ headers: { 'x-api-key': ... } }).
Types
ConfigureApiOptions
Options accepted by configureApi().
type ConfigureApiOptions = Pick<Config, 'baseUrl' | 'fetch' | 'headers' | 'auth'>;Fields
baseUrl(string) — API origin. Defaults to'https://api.coin-communities.xyz'. Don't include/api/v1— operation paths already carry it.fetch(typeof globalThis.fetch) — customfetchimplementation. Useful in environments where you need a polyfill or want to intercept requests.headers(HeadersInit) — default headers merged into every request. Use this to passx-api-key.auth(string | ((auth: Auth) => string | undefined | Promise<string | undefined>)) — bearer token or a function (sync or async) that returns one. Attached to each request that declaresjwt_authsecurity.
SDKInfo
The object shape returned by getSDKInfo().
interface SDKInfo {
name: string;
version: string;
platform: Platform;
}Platform
type Platform = 'react' | 'react-native' | 'node';| Value | Resolved when |
|---|---|
'react' | Bundled for browser environments (the browser conditional export) |
'react-native' | Bundled for React Native (the react-native conditional export) |
'node' | Running in Node.js or when no other condition matches (default) |
Constants
SDK_NAME
const SDK_NAME: stringThe package name string. Value: '@coin-communities/sdk'.
SDK_VERSION
const SDK_VERSION: stringThe current SDK version string.
HTTP API (api.*)
All generated API operations are exported as a namespace called api. Configure the
client once with configureApi(), then call operations directly.
Call pattern
By default operations return { data, error, response }. Pass { throwOnError: true }
to throw on HTTP errors instead.
import { configureApi, api } from '@coin-communities/sdk';
configureApi({
baseUrl: 'https://api.coin-communities.xyz',
headers: { 'x-api-key': 'YOUR_KEY' },
});
const { data, error } = await api.getCommunity({
path: { token_address: '7eYw...' },
});
if (error) {
console.error('failed', error.message);
} else {
console.log(data.community.tokenAddress);
}Operations that take a request body, path params, or query params accept them under the matching keys:
// Path params
await api.getCommunity({ path: { token_address: '7eYw...' } });
// Query params
await api.getMessages({ path: { token_address: '7eYw...' }, query: { limit: 50 } });
// Body
await api.postMessage({
path: { token_address: '7eYw...' },
body: { content: 'gm', chainId: 'solana', walletAddress: 'YourWalletPubkey' },
});Type names
The generated types follow each operation's name. For an operation xxx() you get:
XxxData— request shape (body / path / query / url)XxxResponses— map of status code → response bodyXxxResponse— union of success response bodiesXxxErrors— map of status code → error bodyXxxError— union of error bodies (where applicable)
Refer to types.gen.ts and openapi.json in the SDK package for the full schema.
Operations by domain
Diagnostics
| Operation | HTTP | Auth | Description |
|---|---|---|---|
health | GET /health | none | Liveness check. Returns { status: 'ok' }. |
ping | GET /ping | none | Latency probe. |
Business — Auth
Manages business accounts (the team-level entity that owns API keys, callbacks, and members). Business endpoints use email + password credentials; calls return a JWT used as the bearer token.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
me | GET /api/v1/business/me | jwt | Returns the authenticated business profile. |
login | POST /api/v1/business/login | none | Email + password login. Returns a JWT. |
logout | POST /api/v1/business/logout | jwt | Invalidates the current session. |
register | POST /api/v1/business/register | none | Create a new business account. |
verifyEmail | POST /api/v1/business/verify-email | none | Confirm email via verification code. |
resendVerification | POST /api/v1/business/resend-verification | none | Re-send verification email. |
forgotPassword | POST /api/v1/business/forgot-password | none | Trigger password-reset email. |
resetPassword | POST /api/v1/business/reset-password | none | Complete password reset with code. |
Business — API Keys
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getApiKeys | GET /api/v1/business/api-keys | jwt | List API keys for the business. |
createApiKey | POST /api/v1/business/api-keys | jwt | Create a new API key (key shown once). |
rotateApiKey | POST /api/v1/business/api-keys/{id}/rotate | jwt | Rotate an API key's secret. |
revokeApiKey | DELETE /api/v1/business/api-keys/{id} | jwt | Revoke an API key permanently. |
listApiKeyOrigins | GET /api/v1/business/api-keys/{id}/origins | jwt | List allowed browser origins for an API key. |
addApiKeyOrigin | POST /api/v1/business/api-keys/{id}/origins | jwt | Add an allowed origin. Returns 409 if already present. |
removeApiKeyOrigin | DELETE /api/v1/business/api-keys/{id}/origins/{origin_id} | jwt | Remove an allowed origin. |
Business — Server API Keys
Server API keys authenticate server-side operations that bypass per-user context —
e.g. reading all messages across communities from a backend. They are distinct from
regular API keys and are not usable in browser contexts. Each key is a pair: the
x-server-key identifier and a matching x-server-secret, both of which must be sent
on every server-side request.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getServerApiKeys | GET /api/v1/business/server-api-keys | jwt | List server API keys for the business. |
createServerApiKey | POST /api/v1/business/server-api-keys | jwt | Create a new server API key. Returns key and secret once — store them immediately. |
revokeServerApiKey | DELETE /api/v1/business/server-api-keys/{id} | jwt | Revoke a server API key permanently. |
Business — Callbacks
Webhook URLs the platform POSTs to on community events.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
listCallbacks | GET /api/v1/business/callbacks | jwt | List registered callback URLs. |
addCallback | POST /api/v1/business/callbacks | jwt | Register a callback URL. |
removeCallback | DELETE /api/v1/business/callbacks/{id} | jwt | Remove a callback URL. |
Business — Members
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getMembers | GET /api/v1/business/members | jwt | List team members. |
addMember | POST /api/v1/business/members | jwt | Invite a new team member by email. |
deleteMember | DELETE /api/v1/business/members/{id} | jwt | Remove a team member. |
Business — Logs
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getLogs | GET /api/v1/business/logs | jwt | Read API call audit logs. Accepts GetLogsParams query filters. |
Communities
A community is keyed by its on-chain token_address. Most community operations accept
either jwt_auth or api_key_auth.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getTopCommunities | GET /api/v1/communities/top | none | List top communities by activity. |
getCommunity | GET /api/v1/communities/{token_address} | api key | Fetch community metadata. |
getMessages | GET /api/v1/communities/{token_address}/messages | api key | List messages. Accepts GetMessagesQuery. |
getMessagesPublic | GET /api/v1/communities/{token_address}/messages/public | none | Read messages without authentication. |
postMessage | POST /api/v1/communities/{token_address}/messages | api key | Post a new message. Requires body PostMessageRequest. |
likeMessage | POST /api/v1/communities/{token_address}/messages/{message_id}/like | api key | Like a message. |
unlikeMessage | DELETE /api/v1/communities/{token_address}/messages/{message_id}/like | api key | Remove a like. |
getLikeCount | GET /api/v1/communities/{token_address}/messages/{message_id}/likes | api key | Read the like count for a message. |
getReplies | GET /api/v1/communities/{token_address}/messages/{message_id}/replies | api key | List replies. Accepts GetRepliesQuery. |
postReply | POST /api/v1/communities/{token_address}/messages/{message_id}/replies | api key | Post a reply. Body shape identical to postMessage. |
reportMessage | POST /api/v1/communities/{token_address}/messages/{message_id}/report | api key | Report a message. Accepts ReportMessageRequest. |
getCommunityMembers | GET /api/v1/communities/{token_address}/members | api key | List members. Accepts limit and offset query params. |
getWsTicket | POST /api/v1/communities/{token_address}/ws/ticket | api key | Obtain a short-lived WebSocket ticket for realtime subscriptions. |
getCommunitiesBatch | POST /api/v1/communities/batch | api key | Fetch multiple communities in a single request. Body: BatchGetCommunitiesRequest. |
getMessagePublic | GET /api/v1/communities/messages/{message_id}/public | api key | Fetch a single message by ID without a user session. Returns PublicMessageResponse. |
Community — Server-side operations
These operations authenticate with the x-server-key + x-server-secret pair
(see Business — Server API Keys). They are intended for
trusted server environments and are not safe to call from browsers. Server-side
write operations (postMessageServer, postReplyServer) accept a twitterId in the
body to attribute the post to a user without that user's JWT.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getMessagesServer | GET /api/v1/communities/{token_address}/messages/server | server key + secret | Read all messages (including moderation metadata) for a community. |
postMessageServer | POST /api/v1/communities/{token_address}/messages/server | server key + secret | Post a message on behalf of a user. Body: PostMessageServerRequest. |
getRepliesServer | GET /api/v1/communities/{token_address}/messages/{message_id}/replies/server | server key + secret | Read all replies for a message (including moderation metadata). |
postReplyServer | POST /api/v1/communities/{token_address}/messages/{message_id}/replies/server | server key + secret | Post a reply on behalf of a user. Body: PostMessageServerRequest. |
getCommunityMembersServer | GET /api/v1/communities/{token_address}/members/server | server key + secret | List contributing members for a community. Accepts limit and offset query params. |
getMessagesGlobalServer | GET /api/v1/communities/messages/server | server key + secret | Read messages across all communities. Accepts GetGlobalMessagesQuery. |
getWsTicketServer | POST /api/v1/communities/{token_address}/ws/ticket/server | server key + secret | Obtain a WebSocket ticket scoped to a single community for server-side subscriptions. |
getWsTicketGlobalServer | POST /api/v1/communities/ws/ticket/server/global | server key + secret | Obtain a global WebSocket ticket for server-side subscriptions. |
Community media
| Operation | HTTP | Auth | Description |
|---|---|---|---|
uploadCommunityMedia | POST /api/v1/communities/media | api key | Upload an image for use in a message. Returns a media URL. |
getMediaProviders | GET /api/v1/communities/media-providers | api key | List supported upload providers. |
getSupportedChains | GET /api/v1/communities/chains | api key | List blockchain networks the platform supports. |
Feed
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getFeed | GET /api/v1/feed | api key | Cross-community activity feed (authenticated). |
getFeedPublic | GET /api/v1/feed/public | none | Cross-community activity feed without authentication. |
Users
End-user (not business) profile management. Users authenticate via Twitter OAuth — see Twitter.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
userMe | GET /api/v1/users/me | api key | Returns the authenticated user profile. |
refreshToken | POST /api/v1/users/token/refresh | api key | Exchange a refresh token for a new access token. |
getUserCommunities | GET /api/v1/users/{user_id}/communities | api key | List communities a user belongs to. Accepts limit and offset query params. |
getUserByWallet | GET /api/v1/users/by-wallet/{address} | api key | Look up a user by a linked wallet address. |
getUserIdByTwitterId | GET /api/v1/users/by-twitter-id/{twitter_id} | api key | Resolve a Twitter ID to its platform userId. |
getUsersByWalletBatch | POST /api/v1/users/by-wallet/batch | api key | Look up multiple users by wallet addresses in one request. Body: BatchGetUsersByWalletRequest. |
Wallets
Link EVM and Solana wallets to a user account via a signed challenge.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getWallets | GET /api/v1/users/me/wallets | api key | List linked wallets. |
walletChallenge | POST /api/v1/users/me/wallets/challenge | api key | Request a sign-in challenge for the wallet. |
linkWallet | POST /api/v1/users/me/wallets | api key | Link a wallet using the signed challenge nonce. |
unlinkWallet | DELETE /api/v1/users/me/wallets/{id} | api key | Unlink a wallet. |
User authentication flows. These endpoints require api_key_auth.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
twitterAuthUrl | GET /api/v1/users/twitter/auth-url | api key | Get the Twitter OAuth authorization URL. |
twitterCallback | POST /api/v1/users/twitter/callback | api key | Complete the OAuth flow (legacy token-in-redirect path). |
twitterChallengeExchange | POST /api/v1/users/twitter/challenge/exchange | api key | Exchange a one-time challengeCode for access + refresh tokens. Preferred over twitterCallback. |
User social graph
| Operation | HTTP | Auth | Description |
|---|---|---|---|
getUserProfile | GET /api/v1/users/{user_id}/profile | api key | Fetch a user's public profile. |
getFollowers | GET /api/v1/users/{user_id}/followers | api key | List a user's followers. Accepts limit and offset. |
getFollowing | GET /api/v1/users/{user_id}/following | api key | List users that a user follows. |
followUser | POST /api/v1/users/{user_id}/follow | api key | Follow a user. |
unfollowUser | DELETE /api/v1/users/{user_id}/follow | api key | Unfollow a user. |
Short links
Short-link operations create and resolve opaque link codes for sharing community pages or individual posts. Link codes are scoped to the community identified by tokenAddress.
| Operation | HTTP | Auth | Description |
|---|---|---|---|
createLink | POST /api/v1/links | api key | Create (or return an existing) short link for a community or post. Body: CreateLinkRequest. Returns LinkResponse. |
resolveLink | GET /api/v1/links/{code} | api key | Resolve an opaque short-link code back to its target. Returns LinkResponse. |
Realtime
The SDK ships a WebSocket client for live community updates.
// Resolved automatically when bundled for browser or React Native
import { CommunityRealtimeClient } from '@coin-communities/sdk';
// or explicit subpath
import { CommunityRealtimeClient } from '@coin-communities/sdk/react';
import { CommunityRealtimeClient } from '@coin-communities/sdk/react-native';The realtime module is not available in the node condition. CommunityRealtimeClient,
useCommunityEvents, useCommunityRealtime, realtimeAuthFromApiClient, and
bindCommunityEventsToQueryClient are exported only from the browser (react) and
react-native entry points. In Node.js, import from @coin-communities/sdk/react or
@coin-communities/sdk/react-native explicitly, or use the raw WebSocket API.
CommunityRealtimeClient
A shared WebSocket client per (baseUrl, tokenAddress) pair. Call getOrCreate to
get or lazily spin up a connection; CommunityRealtimeClient handles reconnection with
exponential back-off automatically.
const client = CommunityRealtimeClient.getOrCreate({
baseUrl: 'https://api.coin-communities.xyz',
tokenAddress: '7eYw...',
auth: {
// Fetches a fresh single-use ticket on connect and every reconnect.
getTicket: async () => {
const { data } = await api.getWsTicket({ path: { token_address: '7eYw...' } });
if (!data?.ticket) throw new Error('WebSocket ticket unavailable');
return data.ticket;
},
},
});
const dispose = client.subscribe({
onMessage: (event) => console.log('message persisted', event),
onModeration: (event) => console.log('moderation update', event),
onLike: (event) => console.log('like update', event),
onGap: () => console.log('reconnected — refetch via REST'),
onConnect: () => console.log('connected'),
onDisconnect: () => console.log('disconnected'),
});
// Later:
dispose(); // unsubscribe this handler (connection shared with other subscribers)useCommunityEvents (React hook)
import { useCommunityEvents } from '@coin-communities/sdk';
useCommunityEvents(tokenAddress, {
auth: { getTicket: async () => /* return ws ticket string */ },
onMessage: (event) => { /* message persisted */ },
onModeration: (event) => { /* spam/harmful flags changed */ },
onLike: (event) => { /* like update */ },
onGap: () => { /* reconnected — refetch via REST */ },
});The hook wires up and tears down the subscription with the component lifecycle. Handler callbacks are wrapped in refs so you can pass inline functions without churning the connection.
Because posts are processed asynchronously,
onMessage is how you confirm a submitted post was persisted, and
onModeration is how you learn it was later flagged. See
Realtime events for the useOptimisticCommunityPosts
hook and the lower-level reconciliation recipe.
useCommunityRealtime (React hook)
A thinner counterpart to useCommunityEvents. Instead of accepting event handlers, it
exposes the most recent event envelope and the current connection status, letting you
react in JSX rather than callbacks.
Signature
function useCommunityRealtime(
tokenAddress: string,
options?: UseCommunityRealtimeOptions,
): { lastEvent: RealtimeEvent | null; status: RealtimeStatus }Example
import { useCommunityRealtime } from '@coin-communities/sdk';
function ConnectionBadge({ tokenAddress }: { tokenAddress: string }) {
const { status, lastEvent } = useCommunityRealtime(tokenAddress, {
auth: async () => { /* return ws ticket */ },
});
return <span>{status === 'open' ? '🟢' : '🔴'} {lastEvent?.type}</span>;
}realtimeAuthFromApiClient
Builds a RealtimeGetTicketAuth by fetching a fresh WebSocket ticket via the SDK's
generated REST client. The JWT (Authorization) and/or x-api-key already configured
on the client are forwarded to the ticket endpoint automatically.
Signature
function realtimeAuthFromApiClient(
client: Client,
tokenAddress: string,
): RealtimeGetTicketAuthExample
import { realtimeAuthFromApiClient, CommunityRealtimeClient } from '@coin-communities/sdk';
import { createClient } from '@hey-api/client-fetch';
const httpClient = createClient({ baseUrl: 'https://api.coin-communities.xyz' });
const auth = realtimeAuthFromApiClient(httpClient, '7eYw...');
const rtClient = CommunityRealtimeClient.getOrCreate({
baseUrl: 'https://api.coin-communities.xyz',
tokenAddress: '7eYw...',
auth,
});bindCommunityEventsToQueryClient
Wires a CommunityRealtimeClient into a TanStack Query QueryClient, automatically
invalidating and patching cache entries as realtime events arrive. Useful in scenarios
where you want live cache updates without mounting a React component.
Signature
function bindCommunityEventsToQueryClient(
queryClient: QueryClient,
tokenAddress: string,
options?: { baseUrl?: string; auth?: RealtimeAuth },
): () => voidReturns an unsubscribe function.
Example
import { bindCommunityEventsToQueryClient } from '@coin-communities/sdk';
import { QueryClient } from '@tanstack/react-query';
const qc = new QueryClient();
const unsubscribe = bindCommunityEventsToQueryClient(qc, '7eYw...', {
baseUrl: 'https://api.coin-communities.xyz',
auth: { getTicket: async () => (await api.getWsTicket({ path: { token_address: '7eYw...' } })).data?.ticket ?? '' },
});
// Later:
unsubscribe();Realtime types
These types are exported from the browser and react-native conditions (via the realtime namespace). They are not available from the node condition without an explicit subpath import.
RealtimeAuth
Union of the two supported authentication modes.
type RealtimeAuth = RealtimeGetTicketAuth | RealtimeStaticTicketAuth;RealtimeGetTicketAuth
Preferred production auth: fetches a fresh single-use WebSocket ticket before each connection attempt (and every reconnect). The ticket is obtained via api.getWsTicket and is consumed server-side on the first connection.
interface RealtimeGetTicketAuth {
getTicket: () => Promise<string>;
}RealtimeStaticTicketAuth
Static ticket — suitable for tests or one-shot connections. Tickets are single-use server-side, so reconnects with this mode will fail with 401 Invalid or expired ticket. Prefer RealtimeGetTicketAuth in production.
interface RealtimeStaticTicketAuth {
ticket: string;
}RealtimeHandlers
Subscriber-supplied event handlers. All fields are optional.
interface RealtimeHandlers {
onMessage?: (e: CommunityMessageEvent) => void;
onLike?: (e: LikeUpdatePayload) => void;
onModeration?: (e: ModerationUpdatePayload) => void;
onGap?: () => void;
onConnect?: () => void;
onDisconnect?: () => void;
}onMessage— fired when a new (or updated) message event arrives on the wire.onLike— fired when a like count changes.onModeration— fired when a message'sisSpam/isHarmfulflags change.onGap— fired exactly once per reconnect gap: signals that events may have been missed and the consumer should refetch via REST.onConnect/onDisconnect— connection lifecycle events.
RealtimeEvent
Discriminated union of wire-level event envelopes.
type RealtimeEvent =
| { eventType: 'message_update'; data: CommunityMessageEvent }
| { eventType: 'like_update'; data: LikeUpdatePayload }
| { eventType: 'moderation_update'; data: ModerationUpdatePayload };RealtimeEventTypes
String constant map for the three wire-level event discriminants. Use these instead of raw strings to avoid typos.
const RealtimeEventTypes = {
MessageUpdate: 'message_update',
LikeUpdate: 'like_update',
ModerationUpdate: 'moderation_update',
} as const;RealtimeEventType
Union of the three wire discriminant strings.
type RealtimeEventType = 'message_update' | 'like_update' | 'moderation_update';RealtimeStatus
Connection lifecycle state surfaced by useCommunityRealtime.
type RealtimeStatus = 'connecting' | 'open' | 'closed';CommunityMessageEvent
Payload of a message_update WebSocket event. Mirrors the backend CommunityMessageEvent struct. Notable omissions vs the REST Message type: likeCount, replyCount, and tokenAddress are not present on the broadcast event.
interface CommunityMessageEvent {
id: string;
communityId: string;
businessId: string;
userId: string;
username: string;
userTwitterUrl: string;
profileImageUrl: string | null;
followerCount: number;
content: string;
mediaUrl: string | null;
isSpam: boolean;
isHarmful: boolean;
createdAt: string;
parentMessageId: string | null; // non-null when this is a reply
}LikeUpdatePayload
Payload of a like_update WebSocket event.
interface LikeUpdatePayload {
messageId: string;
liked: boolean; // true = like added; false = like removed
}ModerationUpdatePayload
Payload of a moderation_update WebSocket event — fired when a message's spam/harmful classification changes.
interface ModerationUpdatePayload {
messageId: string;
communityId: string;
isSpam: boolean;
isHarmful: boolean;
}RealtimeClientOptions
Options accepted by the CommunityRealtimeClient constructor (and getOrCreate).
interface RealtimeClientOptions {
baseUrl: string;
tokenAddress: string;
auth?: RealtimeAuth;
reconnectBaseMs?: number; // default 500ms
reconnectCapMs?: number; // default 30 000ms
heartbeatIntervalMs?: number; // default 0 (disabled — see note below)
heartbeatTimeoutMs?: number; // default 10 000ms
}reconnectBaseMs/reconnectCapMs— control the exponential-backoff window for automatic reconnects.heartbeatIntervalMs— application-level ping/pong interval. Disabled by default (0) because the current backend does not echopongframes; enabling this against an unmodified backend will cause forced reconnects. Opt in only when the backend supports it.
Entity types
Community
type Community = {
id: string;
tokenAddress: string;
createdAt: string;
};id— unique community identifier.tokenAddress— on-chain token mint address that keys this community.createdAt— ISO-8601 creation timestamp.
TopCommunity
Returned by getTopCommunities.
type TopCommunity = {
tokenAddress: string;
tokenSymbol: string;
tokenImageUrl?: string | null;
tokenHighResImageUrl?: string | null;
chainId?: number | null;
memberCount: number;
postCount: number;
totalLikes: number;
latestPostAt: number; // Unix ms
};tokenHighResImageUrl— higher-resolution variant oftokenImageUrl, when available.chainId— numeric chain identifier for the token's network.
Message
A community message posted by a user.
type Message = {
id: string;
communityId: string;
businessId: string;
userId: string;
tokenAddress: string;
content: string;
mediaUrl?: string | null;
walletAddress?: string | null;
username: string;
displayName: string;
userTwitterUrl: string;
profileImageUrl?: string | null;
followerCount: number;
likeCount: number;
liked: boolean;
replyCount: number;
parentMessageId?: string | null;
isSpam: boolean;
isHarmful: boolean;
source?: string | null;
deletedAt?: string | null;
deletedReason?: string | null;
createdAt: string;
};walletAddress— the wallet the message was posted from; may benullfor messages posted via server-side operations.displayName— the user's display name at the time the message was posted.liked— whether the currently authenticated user has liked this message.parentMessageId— non-null when this message is a reply.isSpam/isHarmful— server-side content classification flags.source— optional label identifying the posting surface (e.g. embed).deletedAt/deletedReason— set when the message has been soft-deleted.
FeedItem
A cross-community feed entry returned by getFeed / getFeedPublic.
type FeedItem = {
id: string;
communityId: string;
tokenAddress: string;
tokenSymbol?: string | null;
tokenImageUrl?: string | null;
content: string;
mediaUrl?: string | null;
username: string;
displayName: string;
profileImageUrl?: string | null;
userTwitterUrl: string;
walletAddress?: string | null;
followerCount: number;
likeCount: number;
liked?: boolean | null;
replyCount: number;
source?: string | null;
createdAt: string;
};displayName— the user's display name at feed-computation time.walletAddress— the wallet the post was attributed to, when available.liked— present only in the authenticated feed (getFeed);null/absent in the public feed.source— optional label identifying the posting surface.
User
An end-user (community participant), authenticated via Twitter OAuth.
type User = {
id: string;
twitterId: string;
username: string;
profileImageUrl?: string | null;
followerCount: number;
followerCountSyncedAt?: string | null;
nativeFollowerCount: number;
nativeFollowingCount: number;
createdAt: string;
};followerCount— Twitter follower count (synced periodically).nativeFollowerCount/nativeFollowingCount— in-platform social graph counts.
UserProfile
Public profile. Returned by getUserProfile and inside FollowListResponse.
type UserProfile = {
id: string;
username: string;
profileImageUrl?: string | null;
followerCount: number;
nativeFollowerCount: number;
nativeFollowingCount: number;
createdAt: string;
};CommunityMember
A community participant. Returned by getCommunityMembers.
type CommunityMember = {
userId: string;
username: string;
displayName: string;
profileImageUrl?: string | null;
twitterUrl: string;
followerCount: number;
messageCount: number;
};displayName— the member's display name, which may differ from theirusername.
WalletLink
A wallet address linked to a user account.
type WalletLink = {
id: string;
userId: string;
businessId: string;
address: string;
chainType: ChainType;
createdAt: string;
};Business
The team-level entity returned by api.me().
type Business = {
id: string;
name: string;
rateLimitPerSecond: number;
createdAt: string;
};BusinessUser
A member of a business team. Returned inside MeResponse and GetMembersResponse.
type BusinessUser = {
id: string;
businessId: string;
email: string;
emailVerified: boolean;
role: string;
createdAt: string;
};ApiKey
type ApiKey = {
id: string;
businessId: string;
createdBy: string;
name: string;
keyPrefix: string;
keyHash: string;
lastUsedAt?: string | null;
revokedAt?: string | null;
createdAt: string;
};The full key string is only returned once — in the key field of CreateApiKeyResponse
or RotateApiKeyResponse. Store it immediately; it cannot be retrieved again.
ServerApiKey
A server-side API key used with x-server-key authentication. Created and managed
via the getServerApiKeys / createServerApiKey / revokeServerApiKey operations.
type ServerApiKey = {
id: string;
businessId: string;
createdBy: string;
name: string;
keyPrefix: string;
keyHash: string;
lastUsedAt?: string | null;
revokedAt?: string | null;
createdAt: string;
};The full key and secret are only returned once — in the key and secret fields
of CreateServerApiKeyResponse. Store them immediately; they cannot be retrieved again.
ApiKeyOrigin
An allowed-origin entry for an API key.
type ApiKeyOrigin = {
id: string;
apiKeyId: string;
origin: string;
createdAt: string;
};WhitelistedCallback
A registered callback (webhook) URL belonging to a business.
type WhitelistedCallback = {
id: string;
businessId: string;
url: string;
createdAt: string;
};MediaProvider
A platform-approved media host. URLs from approved providers are accepted by postMessage.
type MediaProvider = {
id: string;
name: string;
logoUrl: string;
searchUrl: string;
domains: string[];
};ApiLogEvent
A single API call log entry returned by getLogs.
type ApiLogEvent = {
apiKeyId: string;
businessId: string;
method: string;
path: string;
statusCode: number;
latencyMs: number;
createdAt: string;
};MessageLike
A record of a user liking a message.
type MessageLike = {
messageId: string;
userId: string;
businessId: string;
createdAt: string;
};WsTicketResponse
Returned by getWsTicket, getWsTicketServer, and getWsTicketGlobalServer.
type WsTicketResponse = {
ticket: string;
};Pass ticket to RealtimeGetTicketAuth or directly to CommunityRealtimeClient.
Enums
ChainId
type ChainId = 'solana' | 'ethereum' | 'base' | 'bsc';Identifies the blockchain for a message. Required field in PostMessageRequest.
ChainType
type ChainType = 'evm' | 'svm';Wallet signing scheme. 'svm' = Solana; 'evm' = Ethereum / EVM-compatible chains.
Used in LinkWalletRequest and WalletChallengeRequest.
MessageSortField
type MessageSortField = 'time' | 'likes';Controls the sort field for getMessages. Default 'time'.
MessageSortOrder
type MessageSortOrder = 'desc' | 'asc';Sort direction for getMessages. Default 'desc'.
ReportReason
type ReportReason =
| 'spam'
| 'harassment'
| 'hate_speech'
| 'inappropriate_content'
| 'other';Required field in ReportMessageRequest. When 'other', include a text field.
LinkKind
type LinkKind = 'community' | 'post';| Value | Description |
|---|---|
'community' | Link targets a community page. |
'post' | Link targets a specific message within a community. |
Response types
LinkResponse
Returned by createLink and resolveLink.
type LinkResponse = {
code: string;
kind: LinkKind;
tokenAddress: string;
messageId?: string | null;
};code— opaque short-link code. Construct the shareable URL ashttps://your-app.com/l/${code}and pass thecodetoresolveLinkto retrieve the target.messageId— present whenkind === 'post'.
Request and query types
PostMessageRequest
type PostMessageRequest = {
content: string; // required
chainId: ChainId; // required
walletAddress: string; // required — must be a linked wallet
mediaUrl?: string | null; // must be a URL from uploadCommunityMedia
invalidateCache?: boolean | null; // force-refresh wallet-link and balance-eligibility cache before posting
};invalidateCache— whentrue, drops the server's cached wallet-link and balance-eligibility entries for this wallet before checking, forcing a fresh DB/RPC lookup. Use only when you suspect a stale cache entry is blocking a post.
Errors — 400 invalid body; 403 wallet not linked or insufficient token balance.
GetMessagesQuery
Query parameters accepted by getMessages.
type GetMessagesQuery = {
before?: string | null; // cursor (message id) for time-sorted pagination
offset?: number | null; // offset for likes-sorted pagination
limit?: number | null; // default 50, max 100
sort?: MessageSortField | null; // default 'time'
order?: MessageSortOrder | null; // default 'desc'
filterIsSpam?: boolean | null; // exclude spam-classified messages
filterIsHarm?: boolean | null; // exclude harm-classified messages
};GetRepliesQuery
Query parameters accepted by getReplies.
type GetRepliesQuery = {
before?: string | null; // cursor (reply id) for pagination
limit?: number | null;
order?: MessageSortOrder | null; // default 'desc'
};ReportMessageRequest
type ReportMessageRequest = {
reason: ReportReason; // required
text?: string | null; // required when reason is 'other'
};GetLogsParams
Query parameters accepted by getLogs.
type GetLogsParams = {
apiKeyId?: string | null; // filter to a specific API key
method?: string | null; // HTTP method e.g. 'GET'
path?: string | null; // request path prefix
statusClass?: number | null; // 2 = 2xx, 4 = 4xx, 5 = 5xx
startTime?: string | null; // ISO-8601 lower bound
endTime?: string | null; // ISO-8601 upper bound
limit?: number;
offset?: number; // default 0
};LinkWalletRequest
type LinkWalletRequest = {
address: string; // required — wallet public address
chainType: ChainType; // required
signature: string; // required — signature over the nonce from walletChallenge
};Errors — 400 no pending challenge; 401 invalid signature; 409 wallet already linked.
WalletChallengeRequest
type WalletChallengeRequest = {
address: string; // required
chainType: ChainType; // required
};Returns { message: string; nonce: string }. The wallet must sign the message; pass
the resulting signature + address + chainType to linkWallet.
TwitterAuthUrlQuery
type TwitterAuthUrlQuery = {
redirectUrl: string; // required — must be whitelisted in your business dashboard
};The server appends either accessToken+refreshToken (legacy) or a one-time
challengeCode to the redirect URL. Exchange the code via twitterChallengeExchange.
Errors — 400 redirectUrl not whitelisted.
TwitterChallengeExchangeRequest
type TwitterChallengeExchangeRequest = {
challengeCode: string; // single-use, short-lived
};Returns { accessToken, refreshToken, user }. Errors — 404 code expired.
UploadMediaRequest
type UploadMediaRequest = {
contentType: string; // e.g. 'image/jpeg'
data: string; // base64-encoded file content
};Body accepted by uploadCommunityMedia. Returns { mediaUrl: string }.
AddOriginRequest
type AddOriginRequest = {
origin: string; // e.g. 'https://app.example.com' — no path, no trailing slash
};Errors — 404 API key not found; 409 origin already allowed.
BatchGetCommunitiesRequest
Body accepted by getCommunitiesBatch.
type BatchGetCommunitiesRequest = {
tokenAddresses: string[]; // required — list of on-chain token addresses
};Returns BatchGetCommunitiesResponse with a results map keyed by token address.
PostMessageServerRequest
Body accepted by postMessageServer and postReplyServer. Identical to
PostMessageRequest but attributes the post to a user via
twitterId instead of relying on a per-user JWT.
type PostMessageServerRequest = {
content: string; // required
chainId: ChainId; // required
walletAddress: string; // required — must be a linked wallet
twitterId: string; // required — user to attribute the post to
invalidateCache?: boolean | null; // drop cached balance-eligibility before posting
};twitterId— the Twitter ID of the user the message is posted on behalf of.invalidateCache— whentrue, drops the server's cached balance-eligibility entry for this wallet before checking, forcing a fresh RPC/price lookup.
GetGlobalMessagesQuery
Query parameters accepted by getMessagesGlobalServer.
type GetGlobalMessagesQuery = {
before?: string | null; // cursor (message id) for backward pagination
since?: number | null; // lookback: only messages at/after this unix-ms timestamp
limit?: number | null; // default 100, max 500
order?: MessageSortOrder | null;
includeReplies?: boolean | null; // include replies alongside root messages (default false)
filterIsSpam?: boolean | null;
filterIsHarm?: boolean | null;
};CreateLinkRequest
Body accepted by createLink.
type CreateLinkRequest = {
kind: LinkKind; // required
tokenAddress: string; // required — the community token address
messageId?: string | null; // required when kind is 'post'
};kind—'community'for a community page link;'post'for a link to a specific message.messageId— the message to link to. Must be provided whenkind === 'post'.
Errors — 400 invalid body.
PublicMessageResponse
Returned by getMessagePublic. A stripped-down message shape safe for unauthenticated reads.
type PublicMessageResponse = {
id: string;
content: string;
username: string;
displayName: string;
profileImageUrl?: string | null;
likeCount: number;
replyCount: number;
};Errors — 404 message not found.
BatchGetUsersByWallet
Request
Body accepted by getUsersByWalletBatch.
type BatchGetUsersByWalletRequest = {
addresses: string[]; // required — wallet public addresses to look up
};Errors — 400 empty list or too many addresses.
Response
type BatchGetUsersByWalletResponse = {
results: Record<string, BatchUserByWalletResult>;
};
type BatchUserByWalletResult =
| {
status: 'ok';
user_id: string;
twitter_id: string;
username: string;
display_name: string;
profile_image_url?: string | null;
}
| { status: 'notFound' };results is keyed by wallet address. Each entry is either status: 'ok' with the linked profile or status: 'notFound' when no user is linked to that address.