See Agility CMS in action. Watch a product demo
Management SDK - Content
The ContentMethods class provides comprehensive functionality for managing content items, including creation, publication, approval workflows, and retrieval operations.
Bulk Operations Overview
When working with multiple content items, use the bulk methods for better performance:
| Single Item Method | Bulk Method | Use Case |
|---|---|---|
saveContentItem() | saveContentItems(contentItems[]) | Creating/updating multiple items |
publishContent() | batchWorkflowContent(contentIDs[]) | Publishing multiple items at once |
unPublishContent() | batchWorkflowContent(contentIDs[]) | Unpublishing multiple items at once |
Important:
- Bulk methods accept arrays - pass ALL your items/IDs in a single call
- Returns content IDs in the same order as the input array, allowing you to correlate results with your original items
Function List
| Function | Description |
|---|---|
| getContentItem | Retrieves a specific content item by ID |
| publishContent | Publishes a single content item |
| unPublishContent | Unpublishes a single content item |
| batchWorkflowContent | Bulk workflow operation on multiple content items |
| contentRequestApproval | Requests approval for a content item |
| approveContent | Approves a content item |
| declineContent | Declines a content item |
| deleteContent | Deletes a content item |
| saveContentItem | Saves a single content item |
| saveContentItems | Saves multiple content items (bulk) |
| getContentItems | Retrieves content items with filtering (deprecated) |
| getContentList | Retrieves content list with advanced filtering |
| getContentHistory | Retrieves content item history |
| getContentComments | Retrieves content item comments |
getContentItem
Retrieves a specific content item by ID and locale.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentID | number | Yes | The ID of the content item to retrieve |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code (e.g., 'en-us') |
Returns
Promise<ContentItem> - The content item object
Usage Example
const contentItem = await client.contentMethods.getContentItem(123, "your-guid", "en-us")
console.log(contentItem.fields.title)
publishContent
Publishes a single content item through the batch workflow system.
Note: For publishing multiple items, use batchWorkflowContent() with WorkflowOperationType.Publish instead.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentID | number | Yes | The ID of the content item to publish |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| comments | string | No | Optional comments for the publish operation |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
Returns
Promise<number[]> - Array containing the content ID that was published
Usage Example
// Publish a single item
const publishedIds = await client.contentMethods.publishContent(123, "your-guid", "en-us", "Publishing update")
console.log("Published ID:", publishedIds[0])
// Return batch ID immediately for custom polling
const batchId = await client.contentMethods.publishContent(123, "your-guid", "en-us", null, true)
unPublishContent
Unpublishes a single content item through the batch workflow system.
Note: For unpublishing multiple items, use batchWorkflowContent() with WorkflowOperationType.Unpublish instead.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentID | number | Yes | The ID of the content item to unpublish |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| comments | string | No | Optional comments for the unpublish operation |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
Returns
Promise<number[]> - Array containing the content ID that was unpublished
Usage Example
const unpublishedIds = await client.contentMethods.unPublishContent(123, "your-guid", "en-us", "Temporary unpublish")
console.log("Unpublished ID:", unpublishedIds[0])
batchWorkflowContent
Recommended for bulk workflow operations. Performs a batch workflow operation on multiple content items at once. Supports Publish, Unpublish, Approve, Decline, and RequestApproval operations.
Pass ALL your content IDs in a single call instead of calling publishContent() or unPublishContent() in a loop.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentIDs | number[] | Yes | Array of ALL content IDs to process (e.g., [101, 102, 103, 104, ...]) |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| operation | WorkflowOperationType | Yes | The workflow operation (see below) |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
WorkflowOperationType Values
| Value | Description |
|---|---|
WorkflowOperationType.Publish | Publish content items |
WorkflowOperationType.Unpublish | Unpublish content items |
WorkflowOperationType.Approve | Approve content items |
WorkflowOperationType.Decline | Decline content items |
WorkflowOperationType.RequestApproval | Request approval for content items |
Returns
Promise<number[]> - Array of content IDs that were processed, in the same order as the input array
Important Notes
- Pass Multiple IDs: This method accepts an array of content IDs - pass ALL your IDs in one call (e.g.,
[101, 102, 103, 104, 105]), not one at a time. - Order Preservation: The returned content IDs array maintains the same order as your input
contentIDsarray. - Performance: Always use this method for bulk operations instead of calling single-item methods in a loop.
- Atomic Operation: All items are processed as a single batch operation.
Usage Examples
Publish Multiple Items at Once
import {WorkflowOperationType} from "@agility/management-sdk"
// Pass ALL content IDs you want to publish in a single array
const contentIDsToPublish = [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
const publishedIds = await client.contentMethods.batchWorkflowContent(
contentIDsToPublish, // All IDs in one call
"your-guid",
"en-us",
WorkflowOperationType.Publish,
)
// Returns all IDs in the same order: [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
console.log("Published:", publishedIds)
Bulk Publish After Save
import {WorkflowOperationType} from "@agility/management-sdk"
// First, bulk save content items
const contentItems: ContentItem[] = [
{
contentID: -1,
properties: {definitionName: "Article", referenceName: "articles"},
fields: {title: "Article 1"},
},
{
contentID: -1,
properties: {definitionName: "Article", referenceName: "articles"},
fields: {title: "Article 2"},
},
{
contentID: -1,
properties: {definitionName: "Article", referenceName: "articles"},
fields: {title: "Article 3"},
},
]
// Save all items - returns IDs in same order
const savedIds = await client.contentMethods.saveContentItems(contentItems, "your-guid", "en-us")
console.log("Saved IDs:", savedIds) // e.g., [101, 102, 103]
// Publish all saved items - returns IDs in same order
const publishedIds = await client.contentMethods.batchWorkflowContent(
savedIds,
"your-guid",
"en-us",
WorkflowOperationType.Publish,
)
console.log("Published IDs:", publishedIds) // [101, 102, 103] - same order
// Correlate results
savedIds.forEach((id, index) => {
console.log(`Item "${contentItems[index].fields.title}" saved as ID ${id} and published`)
})
Bulk Unpublish
const contentIDs = [101, 102, 103]
const unpublishedIds = await client.contentMethods.batchWorkflowContent(
contentIDs,
"your-guid",
"en-us",
WorkflowOperationType.Unpublish,
)
// unpublishedIds[0] = 101
// unpublishedIds[1] = 102
// unpublishedIds[2] = 103
Workflow Approval Process
const contentIDs = [201, 202, 203]
// Step 1: Request approval for all items
const requestedIds = await client.contentMethods.batchWorkflowContent(
contentIDs,
"your-guid",
"en-us",
WorkflowOperationType.RequestApproval,
)
console.log("Approval requested for:", requestedIds)
// Step 2: Approve all items (typically done by an approver)
const approvedIds = await client.contentMethods.batchWorkflowContent(
contentIDs,
"your-guid",
"en-us",
WorkflowOperationType.Approve,
)
console.log("Approved:", approvedIds)
// Step 3: Publish approved items
const publishedIds = await client.contentMethods.batchWorkflowContent(
approvedIds,
"your-guid",
"en-us",
WorkflowOperationType.Publish,
)
console.log("Published:", publishedIds)
Decline Multiple Items
const contentIDs = [301, 302]
const declinedIds = await client.contentMethods.batchWorkflowContent(
contentIDs,
"your-guid",
"en-us",
WorkflowOperationType.Decline,
)
console.log("Declined content IDs:", declinedIds)
contentRequestApproval
Requests approval for a content item through the workflow system.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentID | number | Yes | The ID of the content item |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| comments | string | No | Optional comments for the approval request |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
Returns
Promise<number[]> - Array of content IDs that had approval requested
Usage Example
const requestedIds = await client.contentMethods.contentRequestApproval(123, "your-guid", "en-us", "Ready for review")
approveContent
Approves a content item in the workflow system.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentID | number | Yes | The ID of the content item to approve |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| comments | string | No | Optional comments for the approval |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
Returns
Promise<number[]> - Array of content IDs that were approved
Usage Example
const approvedIds = await client.contentMethods.approveContent(123, "your-guid", "en-us", "Approved for publication")
declineContent
Declines a content item in the workflow system.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentID | number | Yes | The ID of the content item to decline |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| comments | string | No | Optional comments for the decline |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
Returns
Promise<number[]> - Array of content IDs that were declined
Usage Example
const declinedIds = await client.contentMethods.declineContent(123, "your-guid", "en-us", "Needs revision")
deleteContent
Deletes a content item through the batch workflow system.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentID | number | Yes | The ID of the content item to delete |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| comments | string | No | Optional comments for the deletion |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
Returns
Promise<number[]> - Array of content IDs that were deleted
Usage Example
const deletedIds = await client.contentMethods.deleteContent(123, "your-guid", "en-us", "Removing outdated content")
saveContentItem
Saves a single content item (create or update) through the batch workflow system.
Note: For bulk operations, use saveContentItems() instead for better performance.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentItem | ContentItem | Yes | The content item object to save |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
Returns
Promise<number[]> - Array containing the content ID that was saved
ContentItem Structure
interface ContentItem {
contentID: number // Use -1 or 0 for new items, existing ID for updates
properties: {
definitionName: string // The content model name
referenceName: string // The container reference name
itemOrder?: number // Optional ordering
releaseDate?: string // Optional scheduled release date
pullDate?: string // Optional scheduled pull date
}
fields: {
[key: string]: any // Field values matching the content model
}
seo?: {
// Optional SEO properties
metaDescription?: string
metaKeywords?: string
metaHTML?: string
menuVisible?: boolean
sitemapVisible?: boolean
}
scripts?: {
// Optional custom scripts
top?: string
bottom?: string
}
}
Usage Example
// Create a new content item
const newItem: ContentItem = {
contentID: -1, // -1 or 0 for new items
properties: {
definitionName: "BlogPost",
referenceName: "blogposts",
},
fields: {
title: "New Article",
content: "Article content...",
author: "John Doe",
publishDate: "2024-01-15",
},
seo: {
metaDescription: "A great new article",
},
}
const savedIds = await client.contentMethods.saveContentItem(newItem, "your-guid", "en-us")
console.log("Created content ID:", savedIds[0])
// Update an existing content item
const existingItem = await client.contentMethods.getContentItem(123, "your-guid", "en-us")
existingItem.fields.title = "Updated Title"
const updatedIds = await client.contentMethods.saveContentItem(existingItem, "your-guid", "en-us")
saveContentItems
Recommended for bulk operations. Saves multiple content items in a single batch operation.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contentItems | ContentItem[] | Yes | Array of content item objects to save |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| returnBatchId | boolean | No | If true, returns batch ID immediately without waiting |
Returns
Promise<number[]> - Array of content IDs that were saved, in the same order as the input array
Important Notes
- Order Preservation: The returned content IDs array maintains the same order as your input
contentItemsarray. This allows you to correlate each returned ID with its corresponding input item. - Performance: For bulk operations (2+ items), always use
saveContentItems()instead of callingsaveContentItem()in a loop. - Mixed Operations: You can mix new items (
contentID: -1) and updates (existingcontentID) in the same batch.
Note: If you receive a -1 as part of the return array, that means there was a problem in saving your item. We are working improving our messaging to get you the exact error message in those cases, but until then, the recommendation is to log that save failure and check into manually.
Usage Examples
Basic Bulk Save
const contentItems: ContentItem[] = [
{
contentID: -1,
properties: {definitionName: "BlogPost", referenceName: "blogposts"},
fields: {title: "Article 1", slug: "article-1"},
},
{
contentID: -1,
properties: {definitionName: "BlogPost", referenceName: "blogposts"},
fields: {title: "Article 2", slug: "article-2"},
},
{
contentID: -1,
properties: {definitionName: "BlogPost", referenceName: "blogposts"},
fields: {title: "Article 3", slug: "article-3"},
},
]
const savedIds = await client.contentMethods.saveContentItems(contentItems, "your-guid", "en-us")
// savedIds[0] corresponds to 'Article 1'
// savedIds[1] corresponds to 'Article 2'
// savedIds[2] corresponds to 'Article 3'
console.log("Created IDs:", savedIds)
Correlating Results with Input Data
// Example: Import products and track their new IDs
const products = [
{sku: "SKU-001", name: "Product A", price: 29.99},
{sku: "SKU-002", name: "Product B", price: 49.99},
{sku: "SKU-003", name: "Product C", price: 19.99},
]
const contentItems: ContentItem[] = products.map((product) => ({
contentID: -1,
properties: {definitionName: "Product", referenceName: "products"},
fields: {
sku: product.sku,
name: product.name,
price: product.price,
},
}))
const savedIds = await client.contentMethods.saveContentItems(contentItems, "your-guid", "en-us")
// Map the returned IDs back to original products (same order!)
const productsWithIds = products.map((product, index) => ({
...product,
contentID: savedIds[index],
}))
console.log(productsWithIds)
// [
// { sku: 'SKU-001', name: 'Product A', price: 29.99, contentID: 101 },
// { sku: 'SKU-002', name: 'Product B', price: 49.99, contentID: 102 },
// { sku: 'SKU-003', name: 'Product C', price: 19.99, contentID: 103 }
// ]
Bulk Save and Publish
// Step 1: Save multiple items
const contentItems: ContentItem[] = [
{
contentID: -1,
properties: {definitionName: "NewsArticle", referenceName: "news"},
fields: {title: "Breaking News 1", content: "..."},
},
{
contentID: -1,
properties: {definitionName: "NewsArticle", referenceName: "news"},
fields: {title: "Breaking News 2", content: "..."},
},
]
const savedIds = await client.contentMethods.saveContentItems(contentItems, "your-guid", "en-us")
console.log("Saved content IDs:", savedIds) // e.g., [201, 202]
// Step 2: Publish all saved items using batchWorkflowContent
import {WorkflowOperationType} from "@agility/management-sdk"
const publishedIds = await client.contentMethods.batchWorkflowContent(
savedIds,
"your-guid",
"en-us",
WorkflowOperationType.Publish,
)
console.log("Published content IDs:", publishedIds) // [201, 202] - same order
Mixed Create and Update Operations
const contentItems: ContentItem[] = [
// New item
{
contentID: -1,
properties: {definitionName: "BlogPost", referenceName: "blogposts"},
fields: {title: "Brand New Post"},
},
// Update existing item
{
contentID: 456, // Existing content ID
properties: {definitionName: "BlogPost", referenceName: "blogposts"},
fields: {title: "Updated Existing Post"},
},
]
const savedIds = await client.contentMethods.saveContentItems(contentItems, "your-guid", "en-us")
// savedIds[0] = new ID for 'Brand New Post'
// savedIds[1] = 456 (the updated item retains its ID)
getContentItems
Retrieves content items with basic filtering parameters (deprecated - use getContentList instead).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| referenceName | string | Yes | The reference name of the content model |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| listParams | ListParams | Yes | Pagination and filtering parameters |
Returns
Promise<ContentList> - The content list with items and pagination info
Usage Example
const listParams = {
take: 10,
skip: 0,
sortField: "title",
sortDirection: "asc",
}
const contentList = await client.contentMethods.getContentItems("articles", "your-guid", "en-us", listParams)
getContentList
Retrieves content items with advanced filtering using POST request with filter object.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| referenceName | string | Yes | The reference name of the content model |
| guid | string | Yes | The website GUID |
| locale | string | Yes | The locale code |
| listParams | ListParams | Yes | Pagination and filtering parameters |
| filterObject | ContentListFilterModel | No | Advanced filter criteria |
Returns
Promise<ContentList> - The content list with items and pagination info
Usage Example
const listParams = {
take: 20,
skip: 0,
sortField: "dateCreated",
sortDirection: "desc",
showDeleted: false,
}
const filterObject = {
publishedState: "published",
searchText: "important",
}
const contentList = await client.contentMethods.getContentList(
"articles",
"your-guid",
"en-us",
listParams,
filterObject,
)
getContentHistory
Retrieves the history of changes for a specific content item.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| locale | string | Yes | The locale code |
| guid | string | Yes | The website GUID |
| contentID | number | Yes | The ID of the content item |
| take | number | No | Number of history entries to retrieve (default: 50) |
| skip | number | No | Number of history entries to skip (default: 0) |
Returns
Promise<ContentItemHistory> - The content item history with pagination
Usage Example
const history = await client.contentMethods.getContentHistory("en-us", "your-guid", 123, 25, 0)
console.log(history.items.length)
getContentComments
Retrieves comments for a specific content item.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| locale | string | Yes | The locale code |
| guid | string | Yes | The website GUID |
| contentID | number | Yes | The ID of the content item |
| take | number | No | Number of comments to retrieve (default: 50) |
| skip | number | No | Number of comments to skip (default: 0) |
Returns
Promise<ItemComments> - The content item comments with pagination
Usage Example
const comments = await client.contentMethods.getContentComments("en-us", "your-guid", 123, 10, 0)
console.log(comments.items.length)
Best Practices for Imports and Syncs
When importing content from external systems or syncing with third-party data sources, follow these guidelines for optimal performance and reliability.
Recommended Approach
- Do all lookups first - Check which items already exist before making any changes
- Batch your saves - Use
saveContentItems()to save multiple items in a single call - Batch your publishes - Use
batchWorkflowContent()to publish all saved items at once - Use single-threaded processing - Process batches sequentially, not in parallel
Why Avoid Parallelism?
Do NOT use parallel API calls to speed up imports. While it may seem faster, parallel requests can:
- Overwhelm the API and cause rate limiting
- Lead to race conditions and inconsistent state
- Result in batch conflicts and failed operations
Instead, batch your updates in chunks and process them sequentially in a single thread.
Strategy for Large Imports
For large datasets or ongoing syncs with external systems:
import {WorkflowOperationType} from "@agility/management-sdk"
async function syncExternalData(externalItems: ExternalItem[]) {
const guid = "your-guid"
const locale = "en-us"
// Step 1: Pull existing content list and build a lookup map
const existingContent = await client.contentMethods.getContentList(
"products",
guid,
locale,
{take: 1000, skip: 0}, // Adjust based on your data size
)
// Build a map for fast duplicate checking (key = external ID or SKU)
const existingMap = new Map<string, number>()
for (const item of existingContent.items) {
if (item.fields.externalId) {
existingMap.set(item.fields.externalId, item.contentID)
}
}
// Step 2: Separate items into creates vs updates
const itemsToCreate: ContentItem[] = []
const itemsToUpdate: ContentItem[] = []
for (const ext of externalItems) {
const existingId = existingMap.get(ext.externalId)
if (existingId) {
// Update existing item
itemsToUpdate.push({
contentID: existingId,
properties: {definitionName: "Product", referenceName: "products"},
fields: {name: ext.name, price: ext.price, externalId: ext.externalId},
})
} else {
// Create new item
itemsToCreate.push({
contentID: -1,
properties: {definitionName: "Product", referenceName: "products"},
fields: {name: ext.name, price: ext.price, externalId: ext.externalId},
})
}
}
// Step 3: Process in batches (recommended batch size: 50-100 items)
const BATCH_SIZE = 50
const allSavedIds: number[] = []
// Process creates in batches
for (let i = 0; i < itemsToCreate.length; i += BATCH_SIZE) {
const batch = itemsToCreate.slice(i, i + BATCH_SIZE)
const savedIds = await client.contentMethods.saveContentItems(batch, guid, locale)
allSavedIds.push(...savedIds)
console.log(`Created batch ${Math.floor(i / BATCH_SIZE) + 1}: ${savedIds.length} items`)
}
// Process updates in batches
for (let i = 0; i < itemsToUpdate.length; i += BATCH_SIZE) {
const batch = itemsToUpdate.slice(i, i + BATCH_SIZE)
const savedIds = await client.contentMethods.saveContentItems(batch, guid, locale)
allSavedIds.push(...savedIds)
console.log(`Updated batch ${Math.floor(i / BATCH_SIZE) + 1}: ${savedIds.length} items`)
}
// Step 4: Publish all saved items in batches
for (let i = 0; i < allSavedIds.length; i += BATCH_SIZE) {
const batch = allSavedIds.slice(i, i + BATCH_SIZE)
await client.contentMethods.batchWorkflowContent(batch, guid, locale, WorkflowOperationType.Publish)
console.log(`Published batch ${Math.floor(i / BATCH_SIZE) + 1}: ${batch.length} items`)
}
return {
created: itemsToCreate.length,
updated: itemsToUpdate.length,
published: allSavedIds.length,
}
}
Strategy for Small Lists or Initial Imports
For smaller datasets or one-time initial imports, you can simplify by pulling the entire content list for local duplicate checking:
async function initialImport(sourceData: SourceItem[]) {
const guid = "your-guid"
const locale = "en-us"
// For initial imports or small lists: pull everything and check locally
const existing = await client.contentMethods.getContentList("articles", guid, locale, {take: 5000, skip: 0})
// Build hashtable/map for O(1) duplicate lookups
const existingBySlug = new Map(existing.items.map((item) => [item.fields.slug, item.contentID]))
// Filter to only new items
const newItems = sourceData.filter((item) => !existingBySlug.has(item.slug))
if (newItems.length === 0) {
console.log("No new items to import")
return
}
// Transform and save all new items
const contentItems = newItems.map((item) => ({
contentID: -1,
properties: {definitionName: "Article", referenceName: "articles"},
fields: {title: item.title, slug: item.slug, body: item.body},
}))
const savedIds = await client.contentMethods.saveContentItems(contentItems, guid, locale)
// Publish all at once
const publishedIds = await client.contentMethods.batchWorkflowContent(
savedIds,
guid,
locale,
WorkflowOperationType.Publish,
)
console.log(`Imported and published ${publishedIds.length} new items`)
}
Summary
| Scenario | Strategy |
|---|---|
| Large ongoing sync | Pull existing → build map → batch saves → batch publishes |
| Small list / initial import | Pull all existing → local duplicate check → single batch save → single batch publish |
| Any import | Always use sequential batching, never parallel requests |
Complete Bulk Workflow Example
This example demonstrates a complete workflow for bulk creating, saving, and publishing content items while tracking the correlation between input data and resulting content IDs.
import agilityMgmt, {WorkflowOperationType} from "@agility/management-sdk"
async function bulkImportAndPublish() {
const client = agilityMgmt.getApi({
location: "USA",
websiteId: "your-guid",
securityKey: "your-api-key",
})
const guid = "your-guid"
const locale = "en-us"
// Source data to import
const sourceData = [
{externalId: "ext-001", title: "First Article", body: "Content 1..."},
{externalId: "ext-002", title: "Second Article", body: "Content 2..."},
{externalId: "ext-003", title: "Third Article", body: "Content 3..."},
{externalId: "ext-004", title: "Fourth Article", body: "Content 4..."},
]
// Step 1: Transform source data into ContentItem objects
const contentItems = sourceData.map((item) => ({
contentID: -1, // New items
properties: {
definitionName: "Article",
referenceName: "articles",
},
fields: {
title: item.title,
body: item.body,
externalId: item.externalId, // Track original ID in a field
},
}))
// Step 2: Bulk save all items using saveContentItems()
console.log(`Saving ${contentItems.length} content items...`)
const savedIds = await client.contentMethods.saveContentItems(contentItems, guid, locale)
// savedIds are in the SAME ORDER as contentItems input
console.log("Saved content IDs:", savedIds)
// Step 3: Create a mapping of external IDs to Agility content IDs
const idMapping = sourceData.map((item, index) => ({
externalId: item.externalId,
title: item.title,
contentID: savedIds[index], // Same order guarantees correct mapping
}))
console.log("ID Mapping:")
idMapping.forEach((m) => {
console.log(` ${m.externalId} -> contentID: ${m.contentID} ("${m.title}")`)
})
// Step 4: Bulk publish all saved items using batchWorkflowContent()
console.log(`Publishing ${savedIds.length} content items...`)
const publishedIds = await client.contentMethods.batchWorkflowContent(
savedIds,
guid,
locale,
WorkflowOperationType.Publish,
)
// publishedIds are in the SAME ORDER as savedIds input
console.log("Published content IDs:", publishedIds)
// Verify the order is maintained
publishedIds.forEach((id, index) => {
console.log(`Published: ${idMapping[index].title} (contentID: ${id})`)
})
return idMapping
}
// Run the import
bulkImportAndPublish()
.then((mapping) => console.log("Import complete!", mapping))
.catch((err) => console.error("Import failed:", err))
Output Example
Saving 4 content items...
Saved content IDs: [1001, 1002, 1003, 1004]
ID Mapping:
ext-001 -> contentID: 1001 ("First Article")
ext-002 -> contentID: 1002 ("Second Article")
ext-003 -> contentID: 1003 ("Third Article")
ext-004 -> contentID: 1004 ("Fourth Article")
Publishing 4 content items...
Published content IDs: [1001, 1002, 1003, 1004]
Published: First Article (contentID: 1001)
Published: Second Article (contentID: 1002)
Published: Third Article (contentID: 1003)
Published: Fourth Article (contentID: 1004)
Import complete!
Error Handling
All methods throw Exception objects on failure:
try {
const contentItem = await client.contentMethods.getContentItem(123, "your-guid", "en-us")
} catch (error) {
console.error("Failed to get content item:", error.message)
}