Scheduled & Recurring Posts
Overview
Use the Workvivo Updates API to trigger automated weekly or periodic posts based on external data sources such as Excel reports, operational dashboards, or business systems. Rather than relying on someone to manually compose and publish recurring updates, organisations can schedule scripts that pull fresh data, format it into a post, and publish it to Workvivo automatically, ensuring consistent, timely communication without human intervention.
This use case covers creating automated posts on a schedule, dynamically populating content from external data, and targeting posts to specific spaces or audiences.
Value & Benefits
Eliminate manual publishing overhead. Remove the need for someone to remember to post weekly updates, the system handles it automatically on schedule.
Ensure consistency and timeliness. Posts go out at the same time every week (or day, or month) with a predictable format, regardless of holidays, sick days, or workload.
Surface operational data to frontline teams. Translate numbers sitting in spreadsheets or dashboards into digestible updates that reach employees where they already are, in Workvivo.
Reduce information lag. Shorten the gap between data being available and employees being informed, from days (waiting for someone to write it up) to minutes.
Scale communications without scaling headcount. Support dozens of recurring post types (safety stats, sales leaderboards, shift summaries, KPI snapshots) without adding to the comms team's workload.
Applications
Weekly performance summaries. Automatically post team or regional KPIs every Monday morning, pulled from an Excel report or BI tool.
Operational shift handovers. Publish end-of-shift summaries (incidents, completions, open items) to a space at the end of each shift cycle.
Safety and compliance updates. Post weekly safety stats (days without incident, near-miss counts) to relevant spaces, sourced from an operational database.
Sales leaderboards. Publish weekly or daily top-performer updates pulled from CRM data.
HR and people updates. Automate recurring posts like new joiner announcements, work anniversary roundups, or benefits reminders based on HRIS data.
Content digests. Aggregate and post a weekly roundup of new articles, pages, or documents published across the platform.
Technical Details
Before using these examples, complete Quick Start to create an app and API key and find your Base URL and Workvivo-Id.
Request Format Notes
text, user_id or user_external_id, and created_at are required when creating or updating an update. created_at must be UTC in YYYY-MM-DDTHH:MM:SSZ format. A past created_at publishes immediately and backdates the post. A future created_at schedules the post to publish automatically at that time, provided the selected author has permission to create scheduled posts.
The text field is parsed as Workvivo post text. Do not send raw HTML expecting it to render as markup; HTML tags are escaped. Use plain text, line breaks, mentions, links, and supported Workvivo post formatting instead.
Create a Post (Update)
curl -X POST https://api.workvivo.com/v1/updates \
-H "Authorization: Bearer $WORKVIVO_TOKEN" \
-H "Workvivo-Id: $WORKVIVO_ORG_ID" \
-H "Accept: application/json" \
--form-string $'text=Weekly Sales Summary - Week 24\n\nTotal revenue: EUR 1.2M (+8% WoW)\n\nTop performer: Sarah K. (Dublin)' \
-F "user_id=$WORKVIVO_POST_AUTHOR_ID" \
-F "created_at=2026-06-15T08:00:00Z"
{
"data": {
"id": 24,
"legacy_system_id": null,
"text": "Weekly Sales Summary - Week 24\n\nTotal revenue: EUR 1.2M (+8% WoW)\n\nTop performer: Sarah K. (Dublin)",
"created_at": "2026-06-15T08:00:00.000000Z",
"audience": {
"type": "Global"
},
"permalink": "https://yourcompany.workvivo.com/update/24"
},
"status": "success",
"meta": {}
}
Create a Post with Targeted Audience
curl -X POST https://api.workvivo.com/v1/updates \
-H "Authorization: Bearer $WORKVIVO_TOKEN" \
-H "Workvivo-Id: $WORKVIVO_ORG_ID" \
-H "Accept: application/json" \
--form-string $'text=Safety Stats - Week 24\n\nDays without incident: 47\n\nNear misses reported: 3' \
-F "user_id=$WORKVIVO_POST_AUTHOR_ID" \
-F "created_at=2026-06-15T08:00:00Z" \
-F "audience[type]=spaces" \
-F "audience[spaces][0]=$WORKVIVO_TARGET_SPACE_ID"
{
"data": {
"id": 25,
"legacy_system_id": null,
"text": "Safety Stats - Week 24\n\nDays without incident: 47\n\nNear misses reported: 3",
"created_at": "2026-06-15T08:00:00.000000Z",
"audience": {
"type": "Space"
},
"permalink": "https://yourcompany.workvivo.com/update/25"
},
"status": "success",
"meta": {}
}
Delete a Post
Useful for removing a post that was published with incorrect data before a corrected version is re-posted.
curl -X DELETE https://api.workvivo.com/v1/updates/{update_id} \
-H "Authorization: Bearer $WORKVIVO_TOKEN" \
-H "Workvivo-Id: $WORKVIVO_ORG_ID" \
-H "Accept: application/json"
{
"data": {
"id": 24,
"external_id": null
},
"status": "success",
"meta": {}
}
JavaScript Integration Example
Transform a report from your source system into a Workvivo update. A future created_at schedules the update; a current or past value publishes it immediately.
const apiUrl = 'https://api.workvivo.com/v1';
const headers = {
Authorization: `Bearer ${process.env.WORKVIVO_TOKEN}`,
'Workvivo-Id': process.env.WORKVIVO_ORG_ID,
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json',
};
export async function publishWeeklySummary(report, publishAt) {
const text = [
`Weekly Sales Summary - ${report.week}`,
`Total revenue: ${report.revenue} (${report.week_over_week} WoW)`,
`Top performer: ${report.top_performer}`,
`Full report: ${report.report_url}`,
].join('\n\n');
return createUpdate({
text,
externalId: `weekly-sales-${report.week}`,
publishAt,
spaceId: process.env.WORKVIVO_TARGET_SPACE_ID,
authorId: process.env.WORKVIVO_POST_AUTHOR_ID,
});
}
async function createUpdate(update) {
const body = new URLSearchParams({
text: update.text,
external_id: update.externalId,
user_id: update.authorId,
created_at: update.publishAt.toISOString().replace(/\.\d+Z$/, 'Z'),
'audience[type]': 'spaces',
'audience[spaces][0]': update.spaceId,
});
const response = await fetch(`${apiUrl}/updates`, {
method: 'POST',
headers,
body,
});
if (!response.ok) {
throw new Error(`Update creation failed: ${response.status}`);
}
return response.json();
}