Skip to content

Publishing to social platforms is inherently unreliable — tokens expire, platforms rate-limit, network blips happen. The trick is to fail loudly when it's your bug, and recover quietly when it's not.

Categories of failure ​

CategoryExamplesWhat to do
Your buginvalid slug, missing field, wrong formatFix the request; don't retry
Auth issueexpired token, revoked OAuthNotify the user to reconnect
Platform issuerate limit, transient 5xxRetry with backoff
Network issueDNS, timeoutSDK retries automatically

Detecting categories ​

typescript
import { SocifyrError } from '@socifyr/sdk'

try {
  await socifyr.uploads.text(params)
} catch (err) {
  if (!(err instanceof SocifyrError)) throw err

  // Auth issue — surface to user
  if (err.message.includes('Token has expired') || err.message.includes('revoked')) {
    notifyUser('Please reconnect this platform')
    return
  }

  // Validation / your bug
  if (err.status === 400) {
    logError(err)
    throw err
  }

  // Rate limit
  if (err.status === 429) {
    await sleep(60_000)
    return retry()
  }

  // Everything else — log + rethrow
  logError(err)
  throw err
}

Partial failures ​

When a post fans out to N platforms, some can succeed and others fail:

typescript
const upload = await socifyr.uploads.text(params)
const result = await socifyr.uploads.waitForCompletion(upload.id)

if (result.status === 'partial_failure') {
  const failed = result.channels.filter(c => c.result?.status === 'failed')

  for (const ch of failed) {
    console.warn(`${ch.platform}: ${ch.result?.error}`)
  }

  // Retry just the failed ones (idempotent — succeeded channels are skipped)
  await socifyr.uploads.retry(upload.id)
}

When to retry ​

Error message containsRetry?
rate limitYes, after a delay
timeoutYes (SDK already retries; consider re-retry from your code if persistent)
Token has expiredNo — user must reconnect
Token is invalidNo — user must reconnect
connections should not be emptyNo — fix your request
caption too longNo — fix your content
Platform "...is temporarily unavailable"Yes, after several minutes

Webhook-driven retries ​

In production, prefer webhooks over polling. Subscribe to platform.failed and upload.failed to drive retries:

typescript
app.post('/webhooks/socifyr', async (req, res) => {
  if (!verifyWebhook(req)) return res.status(401).end()

  const { event, payload } = req.body

  if (event === 'platform.failed' && isRetryableError(payload.error)) {
    await scheduleRetry(payload.uploadId, { delayMinutes: 10 })
  }

  res.json({ ok: true })
})

Logging ​

Log enough context to debug, never log the API key. The fields you want:

typescript
{
  uploadId: upload.id,
  connections: params.connections,
  status: result.status,
  channels: result.channels.map(c => ({
    platform: c.platform,
    status: c.result?.status,
    error: c.result?.error,
  })),
}