Skip to content

Upload a photo and post it (Node.js)

The three steps of an upload, then a Post that uses it. Node.js 20 or later.

photo.mjs
import { readFile, stat } from 'node:fs/promises'
const API = 'https://app.pubrivo.com/api'
const auth = { Authorization: `Bearer ${process.env.PUBRIVO_KEY}` }
const json = { ...auth, 'Content-Type': 'application/json' }
const path = 'buns.jpg'
const { size } = await stat(path)
// 1. Reserve it.
const reserved = await fetch(`${API}/media`, {
method: 'POST',
headers: json,
body: JSON.stringify({ filename: path, contentType: 'image/jpeg', bytes: size }),
}).then((r) => r.json())
if (reserved.error) throw new Error(reserved.error.message)
const { assetId, uploadUrl } = reserved.data
// 2. Send the bytes to the signed address — no Authorization header here.
const put = await fetch(uploadUrl, {
method: 'PUT',
headers: { 'Content-Type': 'image/jpeg' },
body: await readFile(path),
})
if (!put.ok) throw new Error(`upload failed: ${put.status}`)
// 3. Confirm it arrived whole.
await fetch(`${API}/media/${assetId}/complete`, { method: 'POST', headers: auth })
// Then use it.
const post = await fetch(`${API}/posts`, {
method: 'POST',
headers: json,
body: JSON.stringify({
text: 'Today’s tray.',
channelIds: [process.env.CHANNEL_ID],
scheduledAt: new Date(Date.now() + 60 * 60_000).toISOString(),
media: [{ assetId, altText: 'A tray of cardamom buns, fresh from the oven' }],
}),
}).then((r) => r.json())
console.log(post.data?.variants ?? post.error)