# Pages

> Source: https://agilitycms.com/docs/javascript/management-sdk/pages

The page methods let you read the sitemap, work with page templates (page models), 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 `PageMethods` class, accessed via `client.pageMethods`. Method names follow each SDK's convention: camelCase in JavaScript, PascalCase in .NET.

## Method reference

| Operation | JavaScript | .NET |
| --- | --- | --- |
| Get sitemap | `getSitemap` | `GetSiteMap` |
| Get all page templates | `getPageTemplates` | `GetPageTemplates` |
| Get page template by ID | `getPageTemplate` | `GetPageTemplate` |
| Get page template by name | `getPageTemplateName` | `GetPageTemplateByName` |
| Get page item templates | `getPageItemTemplates` | `GetPageItemTemplates` |
| Save page template | `savePageTemplate` | `SavePageTemplate` |
| Delete page template | `deletePageTemplate` | `DeletePageTemplate` |
| Get page by ID | `getPage` | `GetPage` |
| Save page | `savePage` | `SavePage` |
| Publish page | `publishPage` | `PublishPage` |
| Unpublish page | `unPublishPage` | `UnPublishPage` |
| Delete page | `deletePage` | `DeletePage` |
| Approve page | `approvePage` | `ApprovePage` |
| Decline page | `declinePage` | `DeclinePage` |
| Request approval | `pageRequestApproval` | `PageRequestApproval` |
| Batch workflow across many pages | `batchWorkflowPages` | *not available* |
| Get page history | `getPageHistory` | *not available* |
| Get page comments | `getPageComments` | *not available* |

> **`getPageTemplateName` is not a typo.** In the JavaScript SDK the method that fetches a template *by* name is called `getPageTemplateName` — it returns a whole `PageModel`, not a name. The .NET equivalent reads better as `GetPageTemplateByName`. We document the names the SDKs actually export rather than the ones they should have.

The three methods marked *not available* are missing from the **.NET SDK**, not from the API. Call `POST /api/v1/instance/{guid}/{locale}/page/batch-workflow`, `GET .../page/{id}/history`, and `GET .../page/{id}/comments` directly if you need them from .NET.

## Sitemap

Retrieve the sitemap for a website and locale. Each node exposes its `Path` and `PageID`.

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// 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);
```

```csharp
var sitemap = await client.pageMethods.GetSiteMap(guid, locale);

foreach (var node in sitemap)
{
    Console.WriteLine($"{node?.Path} - Page ID: {node?.PageID}");
}
```

</div>

**.NET signature:** `Task<List<Sitemap?>> GetSiteMap(string guid, string locale)`

## Page templates

Page templates are also called page models. The terms are used interchangeably.

### Get all page templates

Pass `includeModuleZones` to include the template's module zones, and an optional `searchFilter` string to narrow the results.

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Get all page templates
const pageTemplates = await apiClient.pageMethods.getPageTemplates(
  guid,   // instance GUID
  locale, // locale
  true,   // includeModuleZones
  ''      // searchFilter (optional)
);
console.log('Page templates:', pageTemplates);
```

```csharp
var templates = await client.pageMethods.GetPageTemplates(
    guid: guid,
    locale: locale,
    includeModuleZones: true,
    searchFilter: null // optional search string
);

foreach (var template in templates)
{
    Console.WriteLine($"{template?.TemplateName} (ID: {template?.PageTemplateID})");
}
```

</div>

**.NET signature:** `Task<List<PageModel>?> GetPageTemplates(string guid, string locale, bool includeModuleZones, string? searchFilter = null)`

### Get a page template by ID

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Get a specific page template by ID
const pageTemplate = await apiClient.pageMethods.getPageTemplate(
  guid,
  locale,
  pageTemplateId // template ID
);
console.log('Page template:', pageTemplate);
```

```csharp
var template = await client.pageMethods.GetPageTemplate(guid, locale, pageTemplateId);
Console.WriteLine($"Template: {template?.TemplateName}");
```

</div>

**.NET signature:** `Task<PageModel?> GetPageTemplate(string guid, string locale, int? pageTemplateId)`

### Get a page template by name

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// 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);
```

```csharp
var template = await client.pageMethods.GetPageTemplateByName(guid, locale, "Home Page");
Console.WriteLine($"Template ID: {template?.PageTemplateID}");
```

</div>

**.NET signature:** `Task<PageModel?> GetPageTemplateByName(string guid, string locale, string? templateName)`

### Get page item templates

A page item template is the module zone — the section where components can be added into a page model.

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Get item templates for a page template
const itemTemplates = await apiClient.pageMethods.getPageItemTemplates(
  guid,
  locale,
  pageTemplateId
);
console.log('Item templates:', itemTemplates);
```

```csharp
var itemTemplates = await client.pageMethods.GetPageItemTemplates(guid, locale, pageTemplateId);

foreach (var zone in itemTemplates)
{
    Console.WriteLine($"Zone: {zone?.Name}");
}
```

</div>

**.NET signature:** `Task<List<ContentSectionDefinition?>> GetPageItemTemplates(string guid, string locale, int? id)`

### Save a page template

Creates the page template if it does not exist, otherwise updates it. Takes a `PageModel` object.

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Save (create or update) a page template
const savedPageTemplate = await apiClient.pageMethods.savePageTemplate(
  guid,
  locale,
  pageModel // PageModel object
);
console.log('Saved page template:', savedPageTemplate);
```

```csharp
using agility.models;

var savedTemplate = await client.pageMethods.SavePageTemplate(guid, locale, pageModel);
Console.WriteLine($"Saved template: {savedTemplate?.TemplateName}");
```

</div>

**.NET signature:** `Task<PageModel?> SavePageTemplate(string guid, string locale, PageModel pageModel)`

### Delete a page template

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Delete a page template by ID
await apiClient.pageMethods.deletePageTemplate(
  guid,
  locale,
  pageTemplateId
);
console.log('Page template deleted.');
```

```csharp
var result = await client.pageMethods.DeletePageTemplate(guid, locale, pageTemplateId);
Console.WriteLine($"Deleted: {result}");
```

</div>

**.NET signature:** `Task<string?> DeletePageTemplate(string guid, string locale, int? pageTemplateId)`

## Page operations

### Get a page by ID

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Get a page by its ID
const page = await apiClient.pageMethods.getPage(
  pageID, // page ID
  guid,
  locale
);
console.log('Page:', page);
```

```csharp
var page = await client.pageMethods.GetPage(pageID, guid, locale);
Console.WriteLine($"Page: {page?.Name}");
```

</div>

**.NET signature:** `Task<PageItem?> GetPage(int? pageID, string guid, string locale)`

### Save a page

> **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](#publish-a-page). See
> [How writes complete](/docs/javascript/management-sdk/getting-started#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. JavaScript SDK and REST only. |

**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:

```ts
savePage(pageItem, guid, locale, parentPageID?, placeBeforePageItemID?,
         returnBatchId?, pageIDInOtherLocale?, otherLocale?, linkExistingComponents?)
```

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// 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
);
```

```csharp
using agility.models;

// Create a new page
var savedPageID = await client.pageMethods.SavePage(
    pageItem: pageItem,
    guid: guid,
    locale: locale,
    parentPageID: -1,           // parent page ID (-1 for root)
    placeBeforePageItemID: -1,  // sibling page ordering (-1 for end)
    pageIDInOtherLocale: -1,    // use to copy from another locale
    otherLocale: null           // source locale if copying
);

Console.WriteLine($"Saved page ID: {savedPageID}");
```

</div>

**.NET signature:** `Task<int?> SavePage(PageItem? pageItem, string guid, string locale, int? parentPageID = -1, int? placeBeforePageItemID = -1, int? pageIDInOtherLocale = -1, string? otherLocale = null)`

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](/docs/javascript/management-sdk/management-sdk-creating-content-and-pages-in-other-locales).

### Publish a page

All of the workflow methods below take an optional `comments` string that is recorded against the page's workflow history.

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Publish a page
const publishedPageIDs = await apiClient.pageMethods.publishPage(
  pageID,
  guid,
  locale,
  'Publishing page' // comments (optional)
);
console.log('Published page IDs:', publishedPageIDs);
```

```csharp
var publishedID = await client.pageMethods.PublishPage(
    pageID: pageID,
    guid: guid,
    locale: locale,
    comments: "Publishing page" // optional
);
Console.WriteLine($"Published page ID: {publishedID}");
```

</div>

**.NET signature:** `Task<int?> PublishPage(int? pageID, string guid, string locale, string? comments = null)`

### Unpublish a page

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Unpublish a page
const unpublishedPageIDs = await apiClient.pageMethods.unPublishPage(
  pageID,
  guid,
  locale,
  'Unpublishing page' // comments (optional)
);
console.log('Unpublished page IDs:', unpublishedPageIDs);
```

```csharp
var unpublishedID = await client.pageMethods.UnPublishPage(pageID, guid, locale, "Taking down temporarily");
```

</div>

**.NET signature:** `Task<int?> UnPublishPage(int? pageID, string guid, string locale, string? comments = null)`

### Delete a page

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Delete a page
const deletedPageIDs = await apiClient.pageMethods.deletePage(
  pageID,
  guid,
  locale,
  'Deleting page' // comments (optional)
);
console.log('Deleted page IDs:', deletedPageIDs);
```

```csharp
var deletedID = await client.pageMethods.DeletePage(pageID, guid, locale, "Removing page");
```

</div>

**.NET signature:** `Task<int?> DeletePage(int? pageID, string guid, string locale, string? comments = null)`

### Approve a page

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Approve a page
const approvedPageIDs = await apiClient.pageMethods.approvePage(
  pageID,
  guid,
  locale,
  'Approving page' // comments (optional)
);
console.log('Approved page IDs:', approvedPageIDs);
```

```csharp
var approvedID = await client.pageMethods.ApprovePage(pageID, guid, locale, "Approved for publication");
```

</div>

**.NET signature:** `Task<int?> ApprovePage(int? pageID, string guid, string locale, string? comments = null)`

### Decline a page

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// Decline a page
const declinedPageIDs = await apiClient.pageMethods.declinePage(
  pageID,
  guid,
  locale,
  'Declining page' // comments (optional)
);
console.log('Declined page IDs:', declinedPageIDs);
```

```csharp
var declinedID = await client.pageMethods.DeclinePage(pageID, guid, locale, "Needs revision");
```

</div>

**.NET signature:** `Task<int?> DeclinePage(int? pageID, string guid, string locale, string? comments = null)`

### Request approval for a page

<div class="code-tabs" data-tabs="JavaScript,.NET">

```ts
// 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);
```

```csharp
var id = await client.pageMethods.PageRequestApproval(pageID, guid, locale, "Ready for review");
```

</div>

**.NET signature:** `Task<int?> PageRequestApproval(int? pageID, string guid, string locale, string? comments = null)`

### Move many pages through workflow at once

`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`.

```ts
import { WorkflowOperationType } from '@agility/management-sdk';

const batchIDs = await apiClient.pageMethods.batchWorkflowPages(
  [101, 102, 103],
  guid,
  locale,
  WorkflowOperationType.Publish
);
```

> JavaScript SDK only. From .NET, call `POST /api/v1/instance/{guid}/{locale}/page/batch-workflow` with `pageIDs` and `operation` as query parameters.

## Page history

Retrieve the version history for a page, paged with `take` and `skip`. Note that the locale argument comes first for this method.

```ts
// 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);
```

> JavaScript SDK only. From .NET, call `GET /api/v1/instance/{guid}/{locale}/page/{id}/history?take=50&skip=0`.

## Page comments

Same shape as history — locale first, then paging.

```ts
const comments = await apiClient.pageMethods.getPageComments(locale, guid, pageID, 50, 0);
```

> JavaScript SDK only. From .NET, call `GET /api/v1/instance/{guid}/{locale}/page/{id}/comments?take=50&skip=0`.

## Error handling (.NET)

The .NET SDK throws `ApplicationException` when a request fails.

```csharp
try
{
    var page = await client.pageMethods.GetPage(pageID, guid, locale);
}
catch (ApplicationException ex)
{
    Console.Error.WriteLine($"Error: {ex.Message}");
}
```
