API reference
10 endpoints, served at https://orbitwrite.com/api/v1. Each one lists the credentials it accepts, its parameters and every response it can give.
/api/v1/campaignsPOST/api/v1/campaignsGET/api/v1/campaigns/searchGET/api/v1/campaigns/{campaignId}PATCH/api/v1/campaigns/{campaignId}DEL/api/v1/campaigns/{campaignId}POST/api/v1/campaigns/{campaignId}/duplicatePOST/api/v1/campaigns/batch-deletePOST/api/v1/campaigns/{campaignId}/decisionPOST/api/v1/campaigns/generateRequires campaign:read. Returns the organization's campaigns, newest first, each with a post count and the next upcoming scheduled post.
An API key or OAuth access token as a bearer token, or a signed-in session.
organizationIdstringSession callers only — an API key already determines the workspace.
At least 1 character.
200CampaignListThe workspace's campaigns
campaignsCampaign[]RequiredidstringRequiredtitlestring | nullRequireddescriptionstring | nullRequiredThe campaign's context/source text.
colorstringRequirediconstring | nullRequiredstartDatestring | nullRequiredISO 8601
endDatestring | nullRequiredISO 8601
postCountintegerRequiredEvery post generated for the campaign, any status
nextScheduledAtstring | nullRequiredISO 8601 of the soonest still-upcoming scheduled post
firstScheduledAtstring | nullRequiredISO 8601 of the earliest fire time among the campaign's posts, any status; null when none has one (drafts have no fire time). With lastScheduledAt, the span a calendar draws the campaign over when startDate/endDate are unset.
lastScheduledAtstring | nullRequiredISO 8601 of the latest fire time among the campaign's posts, any status; null when none has one.
curl -X GET "https://orbitwrite.com/api/v1/campaigns" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY"{
"campaigns": [
{
"id": "string",
"title": "string",
"description": "string",
"color": "string",
"icon": "string",
"startDate": "string",
"endDate": "string",
"postCount": 0,
"nextScheduledAt": "string",
"firstScheduledAt": "string",
"lastScheduledAt": "string"
}
]
}Requires campaign:create. Creates a campaign with no posts. The AI wizard generates posts separately; this is the lightweight counterpart used by the create modal and inline composer form.
An API key or OAuth access token as a bearer token, or a signed-in session.
organizationIdstringSession callers only — an API key already determines the workspace.
At least 1 character.
titlestringRequiredBetween 1 and 200 characters.
descriptionstringAt most 4000 characters.
colorstringPalette color id (shares the tag palette). Omit to keep the default.
"grey""dark-grey""purple""blue""teal""green""yellow""orange""pink""red"iconstring | nullAvatar icon as a prefixed string: emoji:🚀 for a raw emoji, or hi:Rocket01 for a curated hugeicon. Null clears it back to the letter monogram.
At most 64 characters.
startDatestring | nullFormat date-time.
endDatestring | nullFormat date-time.
200CampaignRefResultThe created campaign
curl -X POST "https://orbitwrite.com/api/v1/campaigns" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "string"
}'{
"ok": true,
"campaign": {
"id": "string",
"title": "string",
"description": "string",
"color": "string",
"icon": "string",
"startDate": "string",
"endDate": "string"
}
}Requires campaign:read. Case-insensitive substring match against the campaign title, scoped to the organization. LIKE metacharacters in the query match literally. Powers the command menu's campaign search. Returns at most 20 campaigns, newest first.
An API key or OAuth access token as a bearer token, or a signed-in session.
organizationIdstringSession callers only — an API key already determines the workspace.
At least 1 character.
qstringRequiredAt least 1 character.
200SearchCampaignsResultMatching campaigns, newest first
curl -X GET "https://orbitwrite.com/api/v1/campaigns/search?q=q" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY"{
"items": [
{
"id": "string",
"title": "string",
"color": "string",
"icon": "string"
}
]
}Requires campaign:read. One campaign, with the same post count and next scheduled post the list carries. Its posts are GET /posts?campaignId=.
An API key or OAuth access token as a bearer token, or a signed-in session.
campaignIdstringRequiredAt least 1 character.
200CampaignThe campaign
idstringRequiredtitlestring | nullRequireddescriptionstring | nullRequiredThe campaign's context/source text.
colorstringRequirediconstring | nullRequiredstartDatestring | nullRequiredISO 8601
endDatestring | nullRequiredISO 8601
postCountintegerRequiredEvery post generated for the campaign, any status
nextScheduledAtstring | nullRequiredISO 8601 of the soonest still-upcoming scheduled post
firstScheduledAtstring | nullRequiredISO 8601 of the earliest fire time among the campaign's posts, any status; null when none has one (drafts have no fire time). With lastScheduledAt, the span a calendar draws the campaign over when startDate/endDate are unset.
lastScheduledAtstring | nullRequiredISO 8601 of the latest fire time among the campaign's posts, any status; null when none has one.
curl -X GET "https://orbitwrite.com/api/v1/campaigns/{campaignId}" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY"{
"id": "string",
"title": "string",
"description": "string",
"color": "string",
"icon": "string",
"startDate": "string",
"endDate": "string",
"postCount": 0,
"nextScheduledAt": "string",
"firstScheduledAt": "string",
"lastScheduledAt": "string"
}Requires campaign:update. Edit a campaign's name, description, colour, and date range.
An API key or OAuth access token as a bearer token, or a signed-in session.
campaignIdstringRequiredAt least 1 character.
titlestringRequiredBetween 1 and 200 characters.
descriptionstringOmit to keep the stored description; send an empty string to clear it.
At most 4000 characters.
colorstringPalette color id (shares the tag palette). Omit to keep the default.
"grey""dark-grey""purple""blue""teal""green""yellow""orange""pink""red"iconstring | nullAvatar icon as a prefixed string: emoji:🚀 for a raw emoji, or hi:Rocket01 for a curated hugeicon. Null clears it back to the letter monogram.
At most 64 characters.
startDatestring | nullFormat date-time.
endDatestring | nullFormat date-time.
200CampaignMutationResultThe mutation was applied
okbooleanRequiredcurl -X PATCH "https://orbitwrite.com/api/v1/campaigns/{campaignId}" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "string"
}'{
"ok": true
}Requires campaign:delete. Removes the campaign and everything it generated — its posts (and their approval rows via cascade) and the orphaned per-topic composer groups.
An API key or OAuth access token as a bearer token, or a signed-in session.
campaignIdstringRequiredAt least 1 character.
200CampaignMutationResultThe mutation was applied
okbooleanRequiredcurl -X DELETE "https://orbitwrite.com/api/v1/campaigns/{campaignId}" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY"{
"ok": true
}Requires campaign:create. Copies the campaign's own fields (name, description, colour, date range) into a new campaign. Posts are not copied.
An API key or OAuth access token as a bearer token, or a signed-in session.
campaignIdstringRequiredAt least 1 character.
200CampaignRefResultThe new campaign
curl -X POST "https://orbitwrite.com/api/v1/campaigns/{campaignId}/duplicate" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY"{
"ok": true,
"campaign": {
"id": "string",
"title": "string",
"description": "string",
"color": "string",
"icon": "string",
"startDate": "string",
"endDate": "string"
}
}Requires campaign:delete. Bulk-deletes campaigns owned by the given organization (with their posts and orphaned composer groups). Ids the organization doesn't own are skipped; deletedIds says what was removed.
An API key or OAuth access token as a bearer token, or a signed-in session.
organizationIdstringSession callers only — an API key already determines the workspace.
At least 1 character.
idsstring[]RequiredBetween 1 and 200 items.
200BatchDeleteCampaignsResultThe ids that were deleted
okbooleanRequireddeletedIdsstring[]Requiredcurl -X POST "https://orbitwrite.com/api/v1/campaigns/batch-delete" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
"string"
]
}'{
"ok": true,
"deletedIds": [
"string"
]
}Requires approval:decide — green-lighting a campaign is the same authority as approving a post. Approving releases the campaign's still-pending posts into the scheduled queue; rejecting drops them back to Drafts. Creating a campaign takes only campaign:create; deciding one is a separate authority.
An API key or OAuth access token as a bearer token, or a signed-in session.
campaignIdstringRequiredAt least 1 character.
200CampaignDecisionResultThe decision was recorded
curl -X POST "https://orbitwrite.com/api/v1/campaigns/{campaignId}/decision" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"decision": "approved"
}'{
"ok": true,
"decision": "approved",
"postCount": 0
}Requires campaign:create. Fans out AI generation across the selected accounts and persists a campaign with one composer group per topic, each post held in pending_approval until the campaign is approved.
A signed-in session only. The Orbitwrite app calls this; an API key is refused.
campaignIdstring | nullAttach the generated posts to this already-created bare campaign instead of minting a new one.
At least 1 character.
titlestring | nullAt most 200 characters.
sourcestringRequiredThe article URL or free-text brief the campaign promotes.
Between 1 and 4000 characters.
timelineTypestringRequired"date""evergreen"targetDatestring | nullFormat date-time.
durationstringAt most 40 characters.
adaptPerPlatformbooleanaccountIdsstring[]RequiredAt least 1 item.
topicsobject[]RequiredBetween 1 and 40 items.
scheduledAtstringRequiredFormat date-time.
topicstringRequiredBetween 1 and 280 characters.
200GenerateCampaignResultThe campaign and its generated posts were created
okbooleanRequiredcampaignIdstringRequiredpostCountintegerRequiredcurl -X POST "https://orbitwrite.com/api/v1/campaigns/generate" \
-H "Authorization: Bearer $ORBITWRITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"source": "string",
"timelineType": "date",
"accountIds": [
"string"
],
"topics": [
{
"scheduledAt": "2026-10-01T09:00:00Z",
"topic": "string"
}
]
}'{
"ok": true,
"campaignId": "string",
"postCount": 0
}