
Security News
ECMAScript 2025 Finalized with Iterator Helpers, Set Methods, RegExp.escape, and More
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
@crosspost/sdk
Advanced tools
SDK for interacting with the Crosspost Proxy Service.
This package is designed to be used with near-sign-verify for authenticating requests via a wallet or keypair.
bun install @crosspost/sdk
import * as near from "fastintear"; // or near-api-js for creating key pairs
import { sign } from "near-sign-verify";
import {
CrosspostClient,
// error handling helpers
CrosspostError,
isAuthError,
isPlatformError,
isRateLimitError,
isValidationError
} from '@crosspost/sdk';
import type {
ConnectedAccount,
CreatePostRequest,
} from "@crosspost/sdk";
// Initialize the client
const client = new CrosspostClient({
baseUrl: 'https://your-self-hosted-crosspost-api.com', // Optional: Defaults to official API
});
const authToken = await sign({ signer: near, recipient: "crosspost.near", message: "createPost" });
client.setAuthentication(authToken);
client.setAccountHeader("signer.near")
const connectedAccounts: ApiResponse<ConnectedAccountsResponse> = await client.auth.getConnectedAccounts():
try {
const response = await await client.post.createPost({
targets: [
{
userId: connectedAccounts[0].userId,
platform: connectedAccounts[0].platform
}
],
content: [{
text: "hello world",
media: {
data: imageBlob,
mimeType: 'image/jpeg',
altText: 'a beautiful sunset',
}
}]
} as CreatePostRequest);
console.log('Post created successfully');
console.log('Post ID:', response.id);
console.log('Platform:', response.platform);
console.log('URL:', response.url);
console.log('Created at:', response.createdAt);
} catch (error) {
// Check if it's an authentication error
if (isAuthError(error)) {
console.error('Authentication required. Attempting to authorize...');
// The account must be authorized with the backend
const authorized = await client.auth.authorizeNearAccount();
if (authorized) {
// Retry the operation
return createPost();
}
} else {
// Handle other error types
console.error('Error creating post:', error);
if (error instanceof CrosspostError) {
// Use error utility functions to handle specific cases
if (isPlatformError(error)) {
console.error('Platform:', error.platform);
console.error('Error code:', error.code);
console.error('Details:', error.details);
} else if (isRateLimitError(error)) {
console.error('Rate limited until:', error.details?.rateLimit?.reset);
} else if (isValidationError(error)) {
console.error('Validation errors:', error.details?.validationErrors);
}
// Check if error is recoverable
if (error.recoverable) {
console.log('This error is recoverable - retry may succeed');
}
} else if (error instanceof Error) {
// Handle non-API errors (network issues, etc)
console.error('Unexpected error:', error.message);
}
}
}
client.setAuthentication(authToken: string): Promise<void>
- Sets authentication data, necessary
for non-GET requestsclient.isAuthenticated(): boolean
- Checks if client is authenticatedclient.setAccountHeader(accountId: string): Promise<void>
- Sets X-Near-Account Header,
necessary for GET requestsclient.clear(): boolean
- Clears authentication and account headerclient.auth.authorizeNearAccount(): Promise<ApiResponse<NearAuthorizationResponse>>
- Authorizes
NEAR accountclient.auth.unauthorizeNearAccount(): Promise<ApiResponse<NearAuthorizationResponse>>
-
Unauthorizes NEAR accountclient.auth.getNearAuthorizationStatus(): Promise<ApiResponse<NearAuthorizationResponse>>
-
Checks authorization status for authenticated accountclient.auth.loginToPlatform(platform, options?): Promise<AuthCallbackResponse | ApiResponse<AuthUrlResponse>>
-
Opens popup to initiate OAuth flow with platformclient.auth.refreshToken(platform): Promise<ApiResponse<AuthCallbackResponse>>
- Refreshes
platform tokenclient.auth.refreshProfile(platform): Promise<ApiResponse<ConnectedAccount>>
- Refreshes user
profileclient.auth.getAuthStatus(platform): Promise<ApiResponse<AuthStatusResponse>>
- Gets
authentication statusclient.auth.revokeAuth(platform): Promise<ApiResponse<AuthRevokeResponse>>
- Revokes platform
accessclient.auth.getConnectedAccounts(): Promise<ApiResponse<ConnectedAccountsResponse>>
- Lists
connected accountsEach post operation accepts a request object that includes:
targets
: Array of { platform: string, userId: string }
specifying where to perform the actionAvailable methods:
client.post.createPost(request: CreatePostRequest): Promise<CreatePostResponse>
- Creates posts
on specified platformsclient.post.repost(request: RepostRequest): Promise<RepostResponse>
- Reposts an existing postclient.post.quotePost(request: QuotePostRequest): Promise<QuotePostResponse>
- Quotes an
existing postclient.post.replyToPost(request: ReplyToPostRequest): Promise<ReplyToPostResponse>
- Replies to
a postclient.post.likePost(request: LikePostRequest): Promise<LikePostResponse>
- Likes a postclient.post.unlikePost(request: UnlikePostRequest): Promise<UnlikePostResponse>
- Unlikes a postclient.post.deletePost(request: DeletePostRequest): Promise<DeletePostResponse>
- Deletes postsclient.activity.getLeaderboard(options): Promise<LeaderboardResponse>
- Gets activity
leaderboardclient.activity.getAccountActivity(signerId, options): Promise<AccountActivityResponse>
- Gets
account activityclient.activity.getAccountPosts(signerId, options): Promise<AccountPostsResponse>
- Gets account
postsclient.system.getRateLimits(): Promise<RateLimitsResponse>
- Gets all rate limitsclient.system.getEndpointRateLimit(endpoint): Promise<EndpointRateLimitResponse>
- Gets endpoint
rate limitclient.system.getHealthStatus(): Promise<HealthStatusResponse>
- Gets API health statusThe SDK supports offset-based pagination for endpoints that return large collections:
// Get paginated results with specific limit and offset
const response = await client.activity.getLeaderboard({
limit: 10, // Number of items per page
offset: 20, // Skip the first 20 items
});
// Access pagination metadata
console.log(`Total items: ${response.meta.pagination?.total}`);
console.log(`Current page size: ${response.meta.pagination?.limit}`);
console.log(`Current offset: ${response.meta.pagination?.offset}`);
Post operations always return multi-status responses:
// Operation targeting multiple platforms
const response = await client.post.createPost({
targets: [
{ platform: 'twitter', userId: 'user1' },
{ platform: 'facebook', userId: 'user2' },
],
content: [{ text: 'hello world' }],
});
// Check multi-status summary
console.log(`Total operations: ${response.data.summary.total}`);
console.log(`Successful: ${response.data.summary.succeeded}`);
console.log(`Failed: ${response.data.summary.failed}`);
// Access successful results
response.data.results.forEach((result) => {
console.log(`Success on ${result.platform}: ${result.details.id}`);
});
// Access errors (if any)
if (response.data.errors && response.data.errors.length > 0) {
// Error structure is identical to error.details.errors when all operations fail
response.data.errors.forEach((error) => {
console.log(`Error on ${error.details.platform}: ${error.message}`);
console.log(`Error code: ${error.code}`);
console.log(`Recoverable: ${error.recoverable}`);
});
}
If all operations fail, the SDK throws a CrosspostError
with the same error structure in
details.errors
:
try {
await client.post.createPost({...});
} catch (error) {
if (error instanceof CrosspostError) {
// Error structure is identical to response.data.errors in partial success case
error.details.errors.forEach(err => {
console.log(`Error on ${err.details.platform}: ${err.message}`);
console.log(`Error code: ${err.code}`);
console.log(`Recoverable: ${err.recoverable}`);
});
}
}
This consistent error structure allows you to use the same error handling logic regardless of whether you're dealing with partial failures in a multi-status response or complete failure.
The SDK provides detailed validation error information:
try {
await client.post.createPost({
// Invalid or missing required fields
});
} catch (error) {
if (isValidationError(error)) {
console.error('Validation failed:');
// Access validation error details
if (error.details?.validationErrors) {
Object.entries(error.details.validationErrors).forEach(([field, issues]) => {
console.error(`Field '${field}': ${issues.join(', ')}`);
});
}
}
}
import {
getErrorDetails,
getErrorMessage,
isAuthError,
isContentError,
isMediaError,
isNetworkError,
isPlatformError,
isPostError,
isRateLimitError,
isRecoverableError,
isValidationError,
} from '@crosspost/sdk';
// Check error types
if (isAuthError(error)) {
// Handle authentication errors
}
// Get user-friendly error message
const message = getErrorMessage(error, 'Default message');
// Get error details
const details = getErrorDetails(error);
// Create a text post on Twitter
const textPostResponse = await client.post.createPost({
targets: [{
platform: 'twitter',
userId: 'your-twitter-id',
}],
content: [{
text: 'Hello from Crosspost SDK!',
}],
});
// Create a post with media on multiple platforms
const mediaPostResponse = await client.post.createPost({
targets: [
{ platform: 'twitter', userId: 'your-twitter-id' },
{ platform: 'facebook', userId: 'your-facebook-id' },
],
content: [{
text: 'Check out this image!',
media: [{
data: imageBlob,
mimeType: 'image/jpeg',
altText: 'A beautiful sunset',
}],
}],
});
// Like a post on Twitter
await client.post.likePost({
targets: [{
platform: 'twitter',
userId: 'your-twitter-id',
}],
platform: 'twitter',
postId: '1234567890',
});
// Repost on multiple platforms
await client.post.repost({
targets: [
{ platform: 'twitter', userId: 'your-twitter-id' },
{ platform: 'facebook', userId: 'your-facebook-id' },
],
platform: 'twitter',
postId: '1234567890',
});
// Reply to a post
await client.post.replyToPost({
targets: [{
platform: 'twitter',
userId: 'your-twitter-id',
}],
platform: 'twitter',
postId: '1234567890',
content: [{
text: 'This is a reply',
}],
});
// Delete posts
await client.post.deletePost({
targets: [{
platform: 'twitter',
userId: 'your-twitter-id',
}],
posts: [{
platform: 'twitter',
userId: 'your-twitter-id',
postId: '1234567890',
}],
});
// Get leaderboard
const leaderboard = await client.activity.getLeaderboard({
timeframe: 'week',
limit: 10,
});
// Get account activity
const activity = await client.activity.getAccountActivity('user.near', {
timeframe: 'month',
});
// Get account posts
const posts = await client.activity.getAccountPosts('user.near', {
limit: 20,
offset: 0,
});
// Get all rate limits
const rateLimits = await client.system.getRateLimits();
// Get rate limit for a specific endpoint
const postRateLimit = await client.system.getEndpointRateLimit('post');
FAQs
SDK for interacting with the Crosspost API
The npm package @crosspost/sdk receives a total of 270 weekly downloads. As such, @crosspost/sdk popularity was classified as not popular.
We found that @crosspost/sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
Security News
A new Node.js homepage button linking to paid support for EOL versions has sparked a heated discussion among contributors and the wider community.
Research
North Korean threat actors linked to the Contagious Interview campaign return with 35 new malicious npm packages using a stealthy multi-stage malware loader.