schedulifyx-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # @schedulifyx/sdk
2
+
3
+ Official JavaScript/TypeScript SDK for [SchedulifyX API](https://schedulifyx.com/docs) - Social media scheduling made easy.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @schedulifyx/sdk
9
+ # or
10
+ yarn add @schedulifyx/sdk
11
+ # or
12
+ pnpm add @schedulifyx/sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { Schedulify } from '@schedulifyx/sdk';
19
+
20
+ const client = new Schedulify('sk_live_YOUR_API_KEY');
21
+
22
+ // List all posts
23
+ const posts = await client.posts.list();
24
+ console.log(posts.data);
25
+
26
+ // Create a scheduled post
27
+ const post = await client.posts.create({
28
+ content: 'Hello from the SDK! 🚀',
29
+ accountIds: ['acc_123'],
30
+ publishAt: '2024-12-20T10:00:00Z'
31
+ });
32
+
33
+ // Publish immediately
34
+ await client.posts.publish(post.data.id);
35
+ ```
36
+
37
+ ## Configuration
38
+
39
+ ```typescript
40
+ import { Schedulify } from '@schedulify/sdk';
41
+
42
+ // Simple initialization
43
+ const client = new Schedulify('sk_live_YOUR_API_KEY');
44
+
45
+ // With options
46
+ const client = new Schedulify({
47
+ apiKey: 'sk_live_YOUR_API_KEY',
48
+ baseUrl: 'https://api.schedulifyx.com', // optional
49
+ timeout: 30000 // optional, in ms
50
+ });
51
+ ```
52
+
53
+ ## API Reference
54
+
55
+ ### Posts
56
+
57
+ ```typescript
58
+ // List posts with filters
59
+ const posts = await client.posts.list({
60
+ status: 'scheduled',
61
+ accountId: 'acc_123',
62
+ limit: 20,
63
+ offset: 0
64
+ });
65
+
66
+ // Get single post
67
+ const post = await client.posts.get('post_123');
68
+
69
+ // Create post
70
+ const newPost = await client.posts.create({
71
+ content: 'Hello world!',
72
+ accountIds: ['acc_123', 'acc_456'],
73
+ publishAt: '2024-12-20T10:00:00Z',
74
+ mediaUrls: ['https://example.com/image.jpg'],
75
+ platformOverrides: {
76
+ twitter: { content: 'Hello Twitter! #launch' }
77
+ }
78
+ });
79
+
80
+ // Update post
81
+ await client.posts.update('post_123', {
82
+ content: 'Updated content',
83
+ publishAt: '2024-12-21T10:00:00Z'
84
+ });
85
+
86
+ // Delete post
87
+ await client.posts.delete('post_123');
88
+
89
+ // Publish immediately
90
+ await client.posts.publish('post_123');
91
+ ```
92
+
93
+ ### Accounts
94
+
95
+ ```typescript
96
+ // List all connected accounts
97
+ const accounts = await client.accounts.list();
98
+
99
+ // Filter by platform
100
+ const instagramAccounts = await client.accounts.list({
101
+ platform: 'instagram'
102
+ });
103
+
104
+ // Get single account
105
+ const account = await client.accounts.get('acc_123');
106
+
107
+ // Get Pinterest boards
108
+ const boards = await client.accounts.getPinterestBoards('acc_pinterest_123');
109
+ ```
110
+
111
+ ### Media Upload
112
+
113
+ ```typescript
114
+ // Get presigned upload URL
115
+ const { data } = await client.media.getUploadUrl({
116
+ filename: 'my-image.jpg',
117
+ contentType: 'image/jpeg'
118
+ });
119
+
120
+ // Upload using the presigned URL
121
+ await fetch(data.uploadUrl, {
122
+ method: 'PUT',
123
+ headers: { 'Content-Type': 'image/jpeg' },
124
+ body: imageBuffer
125
+ });
126
+
127
+ // Use mediaUrl in your post
128
+ await client.posts.create({
129
+ content: 'Check out this image!',
130
+ accountIds: ['acc_123'],
131
+ mediaUrls: [data.mediaUrl]
132
+ });
133
+
134
+ // Or use the convenience helper (Node.js)
135
+ const mediaUrl = await client.media.upload(imageBuffer, 'image.jpg', 'image/jpeg');
136
+ ```
137
+
138
+ ### Analytics
139
+
140
+ ```typescript
141
+ // Get overview
142
+ const overview = await client.analytics.overview();
143
+
144
+ // Get account-specific analytics
145
+ const accountAnalytics = await client.analytics.forAccount('acc_123', {
146
+ days: 30
147
+ });
148
+
149
+ // Get all analytics
150
+ const allAnalytics = await client.analytics.list({
151
+ startDate: '2024-01-01',
152
+ endDate: '2024-12-31'
153
+ });
154
+ ```
155
+
156
+ ### Queue
157
+
158
+ ```typescript
159
+ // Get queue schedule
160
+ const queue = await client.queue.getSlots('profile_123');
161
+
162
+ // Set queue schedule
163
+ await client.queue.setSlots({
164
+ profileId: 'profile_123',
165
+ timezone: 'America/New_York',
166
+ slots: [
167
+ { dayOfWeek: 1, time: '09:00' },
168
+ { dayOfWeek: 1, time: '15:00' },
169
+ { dayOfWeek: 2, time: '09:00' }
170
+ ],
171
+ active: true
172
+ });
173
+
174
+ // Get next available slot
175
+ const nextSlot = await client.queue.getNextSlot('profile_123');
176
+
177
+ // Preview upcoming slots
178
+ const preview = await client.queue.preview('profile_123', 10);
179
+ ```
180
+
181
+ ### Usage
182
+
183
+ ```typescript
184
+ const usage = await client.usage();
185
+ console.log(`${usage.data.requestsToday}/${usage.data.dailyLimit} daily requests used`);
186
+ ```
187
+
188
+ ### Multi-Tenant (Enterprise)
189
+
190
+ ```typescript
191
+ // Create a tenant
192
+ const tenant = await client.tenants.create({
193
+ externalId: 'user_123',
194
+ email: 'user@example.com',
195
+ name: 'John Doe'
196
+ });
197
+
198
+ // Get OAuth URL for tenant
199
+ const { data } = await client.tenants.getConnectUrl(tenant.data.id, 'instagram');
200
+ // Redirect user to data.url
201
+
202
+ // List tenant's accounts
203
+ const accounts = await client.tenants.listAccounts(tenant.data.id);
204
+
205
+ // Disconnect account
206
+ await client.tenants.disconnectAccount(tenant.data.id, 'acc_123');
207
+ ```
208
+
209
+ ## Error Handling
210
+
211
+ ```typescript
212
+ import { Schedulify, SchedulifyError } from '@schedulify/sdk';
213
+
214
+ try {
215
+ await client.posts.create({...});
216
+ } catch (error) {
217
+ if (error instanceof SchedulifyError) {
218
+ console.error('API Error:', error.code, error.message);
219
+ console.error('Status:', error.status);
220
+ console.error('Details:', error.details);
221
+ }
222
+ }
223
+ ```
224
+
225
+ ## TypeScript Support
226
+
227
+ Full TypeScript support with exported types:
228
+
229
+ ```typescript
230
+ import type {
231
+ Post,
232
+ Account,
233
+ Analytics,
234
+ Tenant,
235
+ QueueSchedule,
236
+ SchedulifyConfig
237
+ } from '@schedulifyx/sdk';
238
+ ```
239
+
240
+ ## License
241
+
242
+ MIT
@@ -0,0 +1,363 @@
1
+ /**
2
+ * SchedulifyX SDK - Official JavaScript/TypeScript SDK
3
+ * https://schedulifyx.com/docs
4
+ */
5
+ interface SchedulifyConfig {
6
+ apiKey: string;
7
+ baseUrl?: string;
8
+ timeout?: number;
9
+ }
10
+ interface Post {
11
+ id: string;
12
+ content: string;
13
+ mediaUrls?: string[];
14
+ status: 'draft' | 'scheduled' | 'publishing' | 'published' | 'failed';
15
+ publishAt?: string;
16
+ publishNow?: boolean;
17
+ accountIds: string[];
18
+ platformOverrides?: Record<string, {
19
+ content?: string;
20
+ }>;
21
+ createdAt: string;
22
+ updatedAt: string;
23
+ }
24
+ interface Account {
25
+ id: string;
26
+ platform: string;
27
+ platformAccountId: string;
28
+ name: string;
29
+ username?: string;
30
+ profilePicture?: string;
31
+ isActive: boolean;
32
+ createdAt: string;
33
+ }
34
+ interface Analytics {
35
+ accountId: string;
36
+ followers: number;
37
+ following: number;
38
+ posts: number;
39
+ engagement: number;
40
+ updatedAt: string;
41
+ }
42
+ interface AnalyticsOverview {
43
+ totalPosts: number;
44
+ scheduledPosts: number;
45
+ publishedPosts: number;
46
+ failedPosts: number;
47
+ totalAccounts: number;
48
+ activeAccounts: number;
49
+ }
50
+ interface Usage {
51
+ requestsToday: number;
52
+ dailyLimit: number;
53
+ remainingToday: number;
54
+ monthlyRequests: number;
55
+ lastUsedAt: string | null;
56
+ }
57
+ interface Tenant {
58
+ id: string;
59
+ externalId: string;
60
+ email?: string;
61
+ name?: string;
62
+ metadata?: Record<string, unknown>;
63
+ createdAt: string;
64
+ }
65
+ interface QueueSlot {
66
+ dayOfWeek: number;
67
+ time: string;
68
+ }
69
+ interface QueueSchedule {
70
+ id: string;
71
+ profileId: string;
72
+ timezone: string;
73
+ slots: QueueSlot[];
74
+ active: boolean;
75
+ }
76
+ interface MediaUploadResponse {
77
+ uploadUrl: string;
78
+ mediaUrl: string;
79
+ expiresIn: number;
80
+ }
81
+ interface PaginatedResponse<T> {
82
+ data: T[];
83
+ pagination: {
84
+ total: number;
85
+ limit: number;
86
+ offset: number;
87
+ hasMore: boolean;
88
+ };
89
+ }
90
+ interface ApiError {
91
+ code: string;
92
+ message: string;
93
+ details?: Record<string, unknown>;
94
+ }
95
+ declare class SchedulifyError extends Error {
96
+ code: string;
97
+ status: number;
98
+ details?: Record<string, unknown>;
99
+ constructor(message: string, code: string, status: number, details?: Record<string, unknown>);
100
+ }
101
+ declare class Schedulify {
102
+ private apiKey;
103
+ private baseUrl;
104
+ private timeout;
105
+ constructor(config: SchedulifyConfig | string);
106
+ private request;
107
+ posts: {
108
+ /**
109
+ * List all posts with optional filters
110
+ */
111
+ list: (params?: {
112
+ status?: "draft" | "scheduled" | "publishing" | "published" | "failed";
113
+ accountId?: string;
114
+ limit?: number;
115
+ offset?: number;
116
+ }) => Promise<PaginatedResponse<Post>>;
117
+ /**
118
+ * Get a single post by ID
119
+ */
120
+ get: (postId: string) => Promise<{
121
+ data: Post;
122
+ }>;
123
+ /**
124
+ * Create a new post
125
+ */
126
+ create: (data: {
127
+ content: string;
128
+ accountIds: string[];
129
+ publishAt?: string;
130
+ publishNow?: boolean;
131
+ mediaUrls?: string[];
132
+ platformOverrides?: Record<string, {
133
+ content?: string;
134
+ }>;
135
+ }) => Promise<{
136
+ data: Post;
137
+ }>;
138
+ /**
139
+ * Update an existing post
140
+ */
141
+ update: (postId: string, data: {
142
+ content?: string;
143
+ publishAt?: string;
144
+ mediaUrls?: string[];
145
+ }) => Promise<{
146
+ data: Post;
147
+ }>;
148
+ /**
149
+ * Delete a post
150
+ */
151
+ delete: (postId: string) => Promise<{
152
+ success: boolean;
153
+ }>;
154
+ /**
155
+ * Publish a post immediately
156
+ */
157
+ publish: (postId: string) => Promise<{
158
+ data: Post;
159
+ }>;
160
+ };
161
+ accounts: {
162
+ /**
163
+ * List all connected social accounts
164
+ */
165
+ list: (params?: {
166
+ platform?: string;
167
+ limit?: number;
168
+ offset?: number;
169
+ }) => Promise<PaginatedResponse<Account>>;
170
+ /**
171
+ * Get a single account by ID
172
+ */
173
+ get: (accountId: string) => Promise<{
174
+ data: Account;
175
+ }>;
176
+ /**
177
+ * Get Pinterest boards for a Pinterest account
178
+ */
179
+ getPinterestBoards: (accountId: string) => Promise<{
180
+ data: {
181
+ id: string;
182
+ name: string;
183
+ }[];
184
+ }>;
185
+ };
186
+ analytics: {
187
+ /**
188
+ * Get analytics overview
189
+ */
190
+ overview: () => Promise<{
191
+ data: AnalyticsOverview;
192
+ }>;
193
+ /**
194
+ * Get analytics for a specific account
195
+ */
196
+ forAccount: (accountId: string, params?: {
197
+ days?: number;
198
+ }) => Promise<{
199
+ data: Analytics[];
200
+ }>;
201
+ /**
202
+ * Get all analytics data
203
+ */
204
+ list: (params?: {
205
+ accountId?: string;
206
+ startDate?: string;
207
+ endDate?: string;
208
+ }) => Promise<{
209
+ data: Analytics[];
210
+ }>;
211
+ };
212
+ media: {
213
+ /**
214
+ * Get a presigned URL for uploading media
215
+ */
216
+ getUploadUrl: (data: {
217
+ filename: string;
218
+ contentType: string;
219
+ }) => Promise<{
220
+ data: MediaUploadResponse;
221
+ }>;
222
+ /**
223
+ * Helper to upload a file and return the media URL
224
+ */
225
+ upload: (file: Blob | Buffer, filename: string, contentType: string) => Promise<string>;
226
+ };
227
+ /**
228
+ * Get API usage statistics
229
+ */
230
+ usage: () => Promise<{
231
+ data: Usage;
232
+ }>;
233
+ queue: {
234
+ /**
235
+ * Get queue schedule for a profile
236
+ */
237
+ getSlots: (profileId: string) => Promise<{
238
+ data: {
239
+ exists: boolean;
240
+ schedule?: QueueSchedule;
241
+ nextSlots?: string[];
242
+ };
243
+ }>;
244
+ /**
245
+ * Create or update queue schedule
246
+ */
247
+ setSlots: (data: {
248
+ profileId: string;
249
+ timezone: string;
250
+ slots: QueueSlot[];
251
+ active?: boolean;
252
+ reshuffleExisting?: boolean;
253
+ }) => Promise<{
254
+ data: QueueSchedule;
255
+ }>;
256
+ /**
257
+ * Delete queue schedule
258
+ */
259
+ deleteSlots: (profileId: string) => Promise<{
260
+ success: boolean;
261
+ }>;
262
+ /**
263
+ * Get the next available slot
264
+ */
265
+ getNextSlot: (profileId: string) => Promise<{
266
+ data: {
267
+ nextSlot: string;
268
+ timezone: string;
269
+ };
270
+ }>;
271
+ /**
272
+ * Preview upcoming slots
273
+ */
274
+ preview: (profileId: string, count?: number) => Promise<{
275
+ data: {
276
+ slots: string[];
277
+ };
278
+ }>;
279
+ };
280
+ tenants: {
281
+ /**
282
+ * List all tenants
283
+ */
284
+ list: (params?: {
285
+ limit?: number;
286
+ offset?: number;
287
+ search?: string;
288
+ }) => Promise<PaginatedResponse<Tenant>>;
289
+ /**
290
+ * Get a single tenant
291
+ */
292
+ get: (tenantId: string) => Promise<{
293
+ data: Tenant;
294
+ }>;
295
+ /**
296
+ * Create a new tenant
297
+ */
298
+ create: (data: {
299
+ externalId: string;
300
+ email?: string;
301
+ name?: string;
302
+ metadata?: Record<string, unknown>;
303
+ }) => Promise<{
304
+ data: Tenant;
305
+ }>;
306
+ /**
307
+ * Update a tenant
308
+ */
309
+ update: (tenantId: string, data: {
310
+ email?: string;
311
+ name?: string;
312
+ metadata?: Record<string, unknown>;
313
+ }) => Promise<{
314
+ data: Tenant;
315
+ }>;
316
+ /**
317
+ * Delete a tenant
318
+ */
319
+ delete: (tenantId: string) => Promise<{
320
+ success: boolean;
321
+ }>;
322
+ /**
323
+ * Get OAuth URL for tenant to connect a platform
324
+ */
325
+ getConnectUrl: (tenantId: string, platform: string) => Promise<{
326
+ data: {
327
+ url: string;
328
+ };
329
+ }>;
330
+ /**
331
+ * List tenant's connected accounts
332
+ */
333
+ listAccounts: (tenantId: string) => Promise<{
334
+ data: Account[];
335
+ }>;
336
+ /**
337
+ * Disconnect a tenant's account
338
+ */
339
+ disconnectAccount: (tenantId: string, accountId: string) => Promise<{
340
+ success: boolean;
341
+ }>;
342
+ /**
343
+ * Connect Bluesky account for tenant
344
+ */
345
+ connectBluesky: (tenantId: string, data: {
346
+ identifier: string;
347
+ appPassword: string;
348
+ }) => Promise<{
349
+ data: Account;
350
+ }>;
351
+ /**
352
+ * Connect Mastodon account for tenant
353
+ */
354
+ connectMastodon: (tenantId: string, data: {
355
+ instance: string;
356
+ accessToken: string;
357
+ }) => Promise<{
358
+ data: Account;
359
+ }>;
360
+ };
361
+ }
362
+
363
+ export { type Account, type Analytics, type AnalyticsOverview, type ApiError, type MediaUploadResponse, type PaginatedResponse, type Post, type QueueSchedule, type QueueSlot, Schedulify, type SchedulifyConfig, SchedulifyError, type Tenant, type Usage, Schedulify as default };