What is your developer-dependent CMS actually costing you? Calculate your costs and get a full report
What is your developer-dependent CMS actually costing you? Calculate your costs and get a full report
Pages
Create, update, publish, and manage Agility pages, page models, and sitemaps with the Management SDK in JavaScript and .NET.
The page methods let you read the sitemap, work with page models (page templates in the SDK), and create, update, and move pages through workflow — publish, unpublish, approve, decline, request approval, and delete.
In JavaScript these methods live on apiClient.pageMethods. In .NET they live on the PagesClient class, accessed via client.Pages. Method names follow each SDK's convention: camelCase in JavaScript, PascalCase with an Async suffix in .NET. In .NET the instance GUID always comes first, then the locale, then IDs.
The .NET examples on this page use
Agility.Management.SDK2.0. If you are on 1.x, see Migrating to 2.0 for the method names.
| Operation | JavaScript | .NET |
|---|---|---|
| Get sitemap | getSitemap | GetSitemapAsync |
| Get all page models | getPageTemplates | GetPageTemplatesAsync |
| Get page model by ID | getPageTemplate | GetPageTemplateAsync |
| Get page model by name | getPageTemplateName | GetPageTemplateByNameAsync |
| Get page item templates | getPageItemTemplates | GetPageTemplateZonesAsync |
| Save page model | savePageTemplate | SavePageTemplateAsync |
| Delete page model | deletePageTemplate | DeletePageTemplateAsync |
| Get page by ID | getPage | GetPageAsync |
| Save page | savePage | SavePageAsync |
| Publish page | publishPage | PublishPageAsync |
| Unpublish page | unPublishPage | UnpublishPageAsync |
| Delete page | deletePage | DeletePageAsync |
| Approve page | approvePage | ApprovePageAsync |
| Decline page | declinePage | DeclinePageAsync |
| Request approval | pageRequestApproval | RequestApprovalPageAsync |
| Batch workflow across many pages | batchWorkflowPages | BatchWorkflowPagesAsync |
| Get page history | getPageHistory | GetPageHistoryAsync |
| Get page comments | getPageComments | GetPageCommentsAsync |
getPageTemplateNameis not a typo. In the JavaScript SDK the method that fetches a template by name is calledgetPageTemplateName— it returns a wholePageModel, not a name. The .NET equivalent reads better asGetPageTemplateByNameAsync. We document the names the SDKs actually export rather than the ones they should have.
Retrieve the sitemap for a website and locale. It returns one entry per channel, and each channel's pages carry their PageID, with child pages nested under them.
// Get the sitemap for a website and locale
const sitemap = await apiClient.pageMethods.getSitemap(
guid, // instance GUID
locale // locale (e.g., 'en-us')
);
console.log('Sitemap:', sitemap);
var sitemap = await client.Pages.GetSitemapAsync(guid, locale);
foreach (var channel in sitemap)
{
foreach (var node in channel.Pages ?? [])
{
Console.WriteLine($"{node?.Url} - Page ID: {node?.PageID}");
}
}
.NET signature: Task<List<Sitemap>> GetSitemapAsync(string instanceGuid, string locale, CancellationToken cancellationToken = default)
The SDK method names call page models "page templates". The two terms mean the same thing.
Pass includeModuleZones to include the template's zones, and an optional searchFilter string to narrow the results.
// Get all page templates
const pageTemplates = await apiClient.pageMethods.getPageTemplates(
guid, // instance GUID
locale, // locale
true, // includeModuleZones
'' // searchFilter (optional)
);
console.log('Page templates:', pageTemplates);
var templates = await client.Pages.GetPageTemplatesAsync(
guid,
locale,
includeModuleZones: true,
searchFilter: null // optional search string
);
foreach (var template in templates)
{
Console.WriteLine($"{template?.PageTemplateName} (ID: {template?.PageTemplateID})");
}
.NET signature: Task<List<PageModel>> GetPageTemplatesAsync(string instanceGuid, string locale, bool includeModuleZones = false, string searchFilter = null, CancellationToken cancellationToken = default)
// Get a specific page template by ID
const pageTemplate = await apiClient.pageMethods.getPageTemplate(
guid,
locale,
pageTemplateId // template ID
);
console.log('Page template:', pageTemplate);
var template = await client.Pages.GetPageTemplateAsync(guid, locale, pageTemplateId);
Console.WriteLine($"Template: {template?.PageTemplateName}");
.NET signature: Task<PageModel> GetPageTemplateAsync(string instanceGuid, string locale, int pageTemplateId, CancellationToken cancellationToken = default)
// Get a page template by name
const pageTemplateByName = await apiClient.pageMethods.getPageTemplateName(
guid,
locale,
'Home Page' // template name
);
console.log('Page template by name:', pageTemplateByName);
var template = await client.Pages.GetPageTemplateByNameAsync(guid, locale, "Home Page");
Console.WriteLine($"Template ID: {template?.PageTemplateID}");
.NET signature: Task<PageModel> GetPageTemplateByNameAsync(string instanceGuid, string locale, string templateName, CancellationToken cancellationToken = default)
A page item template is a content zone — the section where components can be added into a page model. In .NET 2.0 the method is named for what it returns: GetPageTemplateZonesAsync.
// Get item templates for a page template
const itemTemplates = await apiClient.pageMethods.getPageItemTemplates(
guid,
locale,
pageTemplateId
);
console.log('Item templates:', itemTemplates);
var zones = await client.Pages.GetPageTemplateZonesAsync(guid, locale, pageTemplateId);
foreach (var zone in zones)
{
Console.WriteLine($"Zone: {zone?.PageItemTemplateName}");
}
.NET signature: Task<List<ContentSectionDefinition>> GetPageTemplateZonesAsync(string instanceGuid, string locale, int pageTemplateId, CancellationToken cancellationToken = default)
Creates the page model if it does not exist, otherwise updates it. Takes a PageModel object.
// Save (create or update) a page template
const savedPageTemplate = await apiClient.pageMethods.savePageTemplate(
guid,
locale,
pageModel // PageModel object
);
console.log('Saved page template:', savedPageTemplate);
using Agility.Management.Sdk.Models;
var savedTemplate = await client.Pages.SavePageTemplateAsync(guid, locale, pageModel);
Console.WriteLine($"Saved template: {savedTemplate?.PageTemplateName}");
.NET signature: Task<PageModel> SavePageTemplateAsync(string instanceGuid, string locale, PageModel pageTemplate, CancellationToken cancellationToken = default)
// Delete a page template by ID
await apiClient.pageMethods.deletePageTemplate(
guid,
locale,
pageTemplateId
);
console.log('Page template deleted.');
// Returns no value. A failure throws AgilityManagementException.
await client.Pages.DeletePageTemplateAsync(guid, locale, pageTemplateId);
.NET signature: Task DeletePageTemplateAsync(string instanceGuid, string locale, int pageTemplateId, CancellationToken cancellationToken = default)
// Get a page by its ID
const page = await apiClient.pageMethods.getPage(
pageID, // page ID
guid,
locale
);
console.log('Page:', page);
var page = await client.Pages.GetPageAsync(guid, locale, pageID);
Console.WriteLine($"Page: {page?.Name}");
.NET signature: Task<PageItem> GetPageAsync(string instanceGuid, string locale, int pageId, CancellationToken cancellationToken = default)
Saving is not publishing. A save writes to Staging and returns a batch ID, which the SDK polls on your behalf. A page that was already Published drops back to Staging, and your live site keeps serving the previous version until you call Publish a page. See How writes complete.
Creates the page if it does not exist, otherwise updates it. Takes a PageItem object plus optional placement arguments:
| Parameter | Description |
|---|---|
parentPageID | The parent page to nest under. Use -1 for the root. |
placeBeforePageItemID | The sibling page to place this page before. Use -1 to add at the end. |
pageIDInOtherLocale | The source page ID when copying a page from another locale. |
otherLocale | The source locale when copying. |
linkExistingComponents | When copying across locales, reuse the source page's components instead of duplicating them. In .NET, set SavePageOptions.LinkExistingComponents. |
In .NET these arguments are properties of a SavePageOptions object (ParentPageId, PlaceBeforePageId, PageIdInOtherLocale, OtherLocale, LinkExistingComponents). Settings you leave null use the API's defaults.
Both SDKs support the cross-locale copy arguments — but watch the argument order, because it differs. The JavaScript signature slots returnBatchId in before the locale arguments, so passing otherLocale positionally means supplying returnBatchId first:
savePage(pageItem, guid, locale, parentPageID?, placeBeforePageItemID?,
returnBatchId?, pageIDInOtherLocale?, otherLocale?, linkExistingComponents?)
// Save (create or update) a page
const savedPageIDs = await apiClient.pageMethods.savePage(
pageItem, // PageItem object
guid,
locale,
parentPageID, // parent page ID (optional)
placeBeforePageItemID // place before page ID (optional)
);
console.log('Saved page IDs:', savedPageIDs);
// Copying a page from another locale: returnBatchId comes first
const copied = await apiClient.pageMethods.savePage(
pageItem,
guid,
'fr-ca', // target locale
-1, // parentPageID
-1, // placeBeforePageItemID
false, // returnBatchId
sourcePageID,
'en-us', // otherLocale
true // linkExistingComponents
);
using Agility.Management.Sdk.Clients;
using Agility.Management.Sdk.Models;
// Create a new page
var result = await client.Pages.SavePageAsync(
guid,
locale,
pageItem,
new SavePageOptions
{
ParentPageId = -1, // parent page ID (-1 for root)
PlaceBeforePageId = -1, // sibling page ordering (-1 for end)
// PageIdInOtherLocale and OtherLocale: set these to copy from another locale
});
Console.WriteLine($"Saved page ID: {result.ItemId}");
.NET signature: Task<BatchResult> SavePageAsync(string instanceGuid, string locale, PageItem page, SavePageOptions options = null, bool waitForBatch = true, CancellationToken cancellationToken = default)
Underneath, both map to POST /api/v1/instance/{guid}/{locale}/page, which accepts parentPageID, placeBeforePageItemID, otherLocale, pageIDInOtherLocale, and linkExistingComponents as query parameters.
For the full multi-locale workflow, see Creating content and pages in other locales.
All of the workflow methods below take an optional comments string that is recorded against the page's workflow history. In .NET they return a BatchResult. Use result.ItemId for the page ID.
// Publish a page
const publishedPageIDs = await apiClient.pageMethods.publishPage(
pageID,
guid,
locale,
'Publishing page' // comments (optional)
);
console.log('Published page IDs:', publishedPageIDs);
var published = await client.Pages.PublishPageAsync(
guid,
locale,
pageID,
comments: "Publishing page" // optional
);
Console.WriteLine($"Published page ID: {published.ItemId}");
.NET signature: Task<BatchResult> PublishPageAsync(string instanceGuid, string locale, int pageId, string comments = null, bool waitForBatch = true, CancellationToken cancellationToken = default)
// Unpublish a page
const unpublishedPageIDs = await apiClient.pageMethods.unPublishPage(
pageID,
guid,
locale,
'Unpublishing page' // comments (optional)
);
console.log('Unpublished page IDs:', unpublishedPageIDs);
var unpublished = await client.Pages.UnpublishPageAsync(guid, locale, pageID, "Taking down temporarily");
.NET signature: Task<BatchResult> UnpublishPageAsync(string instanceGuid, string locale, int pageId, string comments = null, bool waitForBatch = true, CancellationToken cancellationToken = default)
// Delete a page
const deletedPageIDs = await apiClient.pageMethods.deletePage(
pageID,
guid,
locale,
'Deleting page' // comments (optional)
);
console.log('Deleted page IDs:', deletedPageIDs);
var deleted = await client.Pages.DeletePageAsync(guid, locale, pageID, "Removing page");
.NET signature: Task<BatchResult> DeletePageAsync(string instanceGuid, string locale, int pageId, string comments = null, bool waitForBatch = true, CancellationToken cancellationToken = default)
// Approve a page
const approvedPageIDs = await apiClient.pageMethods.approvePage(
pageID,
guid,
locale,
'Approving page' // comments (optional)
);
console.log('Approved page IDs:', approvedPageIDs);
var approved = await client.Pages.ApprovePageAsync(guid, locale, pageID, "Approved for publication");
.NET signature: Task<BatchResult> ApprovePageAsync(string instanceGuid, string locale, int pageId, string comments = null, bool waitForBatch = true, CancellationToken cancellationToken = default)
// Decline a page
const declinedPageIDs = await apiClient.pageMethods.declinePage(
pageID,
guid,
locale,
'Declining page' // comments (optional)
);
console.log('Declined page IDs:', declinedPageIDs);
var declined = await client.Pages.DeclinePageAsync(guid, locale, pageID, "Needs revision");
.NET signature: Task<BatchResult> DeclinePageAsync(string instanceGuid, string locale, int pageId, string comments = null, bool waitForBatch = true, CancellationToken cancellationToken = default)
// Request approval for a page
const approvalRequestedPageIDs = await apiClient.pageMethods.pageRequestApproval(
pageID,
guid,
locale,
'Requesting approval' // comments (optional)
);
console.log('Approval requested for page IDs:', approvalRequestedPageIDs);
var requested = await client.Pages.RequestApprovalPageAsync(guid, locale, pageID, "Ready for review");
.NET signature: Task<BatchResult> RequestApprovalPageAsync(string instanceGuid, string locale, int pageId, string comments = null, bool waitForBatch = true, CancellationToken cancellationToken = default)
batchWorkflowPages applies one workflow operation to a list of page IDs in a single call. The operation comes from the WorkflowOperationType enum — Publish, Unpublish, Approve, Decline, or RequestApproval.
import { WorkflowOperationType } from '@agility/management-sdk';
const batchIDs = await apiClient.pageMethods.batchWorkflowPages(
[101, 102, 103],
guid,
locale,
WorkflowOperationType.Publish
);
using Agility.Management.Sdk.Models;
var result = await client.Pages.BatchWorkflowPagesAsync(
guid, locale, [101, 102, 103], WorkflowOperationType.Publish);
REST:
POST /api/v1/instance/{guid}/{locale}/page/batch-workflowwithpageIDsandoperationas query parameters.
Retrieve the version history for a page, paged with take and skip. Note that in JavaScript the locale argument comes first for this method.
// Get history for a page
const pageHistory = await apiClient.pageMethods.getPageHistory(
locale,
guid,
pageID,
50, // take (number of items)
0 // skip (offset)
);
console.log('Page history:', pageHistory);
var history = await client.Pages.GetPageHistoryAsync(guid, locale, pageID, take: 50, skip: 0);
REST:
GET /api/v1/instance/{guid}/{locale}/page/{id}/history?take=50&skip=0.
Same shape as history — locale first in JavaScript, then paging.
const comments = await apiClient.pageMethods.getPageComments(locale, guid, pageID, 50, 0);
var comments = await client.Pages.GetPageCommentsAsync(guid, locale, pageID, take: 50, skip: 0);
REST:
GET /api/v1/instance/{guid}/{locale}/page/{id}/comments?take=50&skip=0.
The .NET SDK throws AgilityManagementException when a request fails. It carries the HTTP status code, the API's error message and a request ID.
try
{
var page = await client.Pages.GetPageAsync(guid, locale, pageID);
}
catch (AgilityManagementException ex)
{
Console.Error.WriteLine($"Error ({ex.StatusCode}): {ex.ApiMessage ?? ex.Message}");
}