The uploads resource is the core of the SDK. Use it for every kind of post.
Methods
| Method | What it does |
|---|---|
text() | Publish text-only content |
photos() | Publish one or more images |
video() | Publish a single video |
document() | Publish a PDF / document |
list() | Paginate post history |
get(id) | Fetch one post |
getStatus(id) | Get the current status + channel results |
waitForCompletion(id) | Poll getStatus until terminal state |
update(id, params) | Edit a draft |
publishDraft(id) | Publish a saved draft |
publishNow(id) | Move a scheduled post forward |
retry(id) | Retry failed channels |
cancel(id) | Delete an upload |
archive(id) / unarchive(id) | Soft archive |
bulkDelete(ids) / bulkArchive(ids) / bulkUnarchive(ids) | Batch ops |
Posting text
typescript
const upload = await socifyr.uploads.text({
connections: ['linkedin-myhandle', 'x-myhandle'],
text: 'Just shipped v2.0 🚀',
})Posting photos
typescript
import { readFileSync } from 'fs'
await socifyr.uploads.photos({
connections: ['instagram-mybrand'],
text: 'Carousel of the week',
medias: [
readFileSync('a.jpg'),
readFileSync('b.jpg'),
'https://cdn.example.com/c.png', // public URL
'6a04f715d3d7d93575e65d13', // media library ID
],
contentFormat: 'photo_carousel',
})medias accepts any mix of:
Buffer/Blob(raw file — auto-uploaded to media library)stringstarting withhttps://orhttp://(public URL)stringmatching/^[a-f\d]{24}$/i(media library ID)
Posting video
typescript
await socifyr.uploads.video({
connections: ['instagram-mybrand', 'tiktok-me'],
text: 'Behind the scenes',
medias: [readFileSync('demo.mp4')],
contentFormat: 'short_video', // make it a reel
})Only one video per post.
Scheduling
Add scheduledAt:
typescript
await socifyr.uploads.text({
connections: ['linkedin-myhandle'],
text: 'Tomorrow at 9am',
scheduledAt: '2026-06-01T09:00:00Z',
timezone: 'America/New_York', // optional, for display
})Drafts
Add saveDraft: true to save without publishing:
typescript
const upload = await socifyr.uploads.photos({
connections: ['instagram-mybrand'],
medias: [readFileSync('banner.jpg')],
text: 'Polish me later',
saveDraft: true,
})
// Later — edit
await socifyr.uploads.update(upload.id, {
text: 'Final caption',
})
// Then publish
await socifyr.uploads.publishDraft(upload.id)Checking status
typescript
const status = await socifyr.uploads.getStatus(upload.id)
// {
// uploadId: '...',
// requestId: '...',
// status: 'partial_failure',
// type: 'text',
// channels: [
// { platform: 'linkedin', result: { status: 'success', postUrl: '...' } },
// { platform: 'x', result: { status: 'failed', error: '...' } },
// ],
// createdAt: '...',
// }
// Or poll until done
const final = await socifyr.uploads.waitForCompletion(upload.id, 3000, 300_000)waitForCompletion(id, intervalMs?, timeoutMs?) blocks until status is completed, failed, or partial_failure.
Retrying
typescript
await socifyr.uploads.retry(upload.id)Successful channels are skipped via an idempotency guard.
Listing history
typescript
const { data, total, page, limit } = await socifyr.uploads.list({
page: 1,
limit: 20,
status: 'completed',
type: 'video',
from: '2026-01-01',
to: '2026-06-01',
})Archive / delete
typescript
await socifyr.uploads.archive(id) // hide from history without deleting
await socifyr.uploads.unarchive(id)
await socifyr.uploads.cancel(id) // hard delete
await socifyr.uploads.bulkDelete([id1, id2, id3])Full type reference
The TypeScript types are exported from the SDK root:
typescript
import type {
Upload,
UploadVideoParams,
UploadPhotosParams,
UploadTextParams,
UploadDocumentParams,
UploadStatusResponse,
UploadStatusChannel,
UpdateDraftParams,
UploadHistoryQuery,
PaginatedResponse,
} from '@socifyr/sdk'