Instapage API
Current state of the API:
What is the Instapage API?
The Instapage API allows developers to interact with the Instapage platform programmatically. By utilizing our API, you can create, update, retrieve, and delete various resources within Instapage, such as landing pages, leads, forms, and more. The API is designed to be RESTful, making it straightforward to integrate with any application or service.
Getting Started
To start using the Instapage API, you'll need to:
- Obtain API Credentials: Generate your API key from the Instapage dashboard.
- Understand API Endpoints: Familiarize yourself with the available endpoints and their functions.
- Make Your First Request: Learn how to authenticate and make basic API requests.
Throughout this documentation, you'll find detailed explanations, code examples, and best practices to help you effectively utilize the Instapage API.
Limitations
API usage limitations are determined by the plan associated with the specific workspace. The token used for requests inherits the permissions of the owner (token creator) who generated it.
Rate Limit: The API allows up to 200 requests per minute. Exceeding this limit will result in a 429 Too Many Requests
response status.
Dictionary
Page
In Instapage, a page is a landing page made within the platform [Creating a new page][How do I publish my page to my own domain]. The page is a standalone webpage for a specific marketing campaign that aims to convert visitors into leads or customers[Lead management].
Workspace
In Instapage, a workspace is a designated area for managing landing pages for a company or project. Multiple workspaces can be created, and each workspace keeps its pages, integrations, domains, and other assets separate from other workspaces[Workspace settings and account settings].
Scheduling
Scheduling allows users to set specific dates and times to publish and unpublish landing pages. Scheduling is available for Custom Domain (CNAME) and Demo Page publishing and offers flexibility for campaign management[Scheduling].
Personalization
Personalization involves creating customized experiences for different audience segments on landing pages. This feature allows users to tailor content and design to resonate with specific visitor groups, enhancing engagement and conversion rates[Personalization creating personalized experiences for different audiences].
Leads
A lead is information submitted by a visitor through a form on a landing page. Lead generation is a crucial aspect of digital marketing, and landing pages are often a primary tool for capturing leads. If a form collects a visitor's name, email, city, and zip code, that constitutes a lead[Lead management].
Changelog
2025-03-11
Added
Groups
We introduced a new Groups API to help users manage page groups (folders) within a workspace.
GET https://api.instapage.com/v1/workspaces/{workspaceId}/groups
- Retrieve all groups (folders) for a specific workspace.POST https://api.instapage.com/v1/workspaces/{workspaceId}/groups
- Create a new group (folder) in a workspace.PUT https://api.instapage.com/v1/workspaces/{workspaceId}/groups/{groupId}
- Update an existing group name (folder) in a workspace.DELETE https://api.instapage.com/v1/workspaces/{workspaceId}/groups/{groupId}
- Delete an empty group (folder) from a workspace.
2025-02-27
Added
Team Members
We enhanced the Team Members API to allow better workspace management by enabling bulk invitations, role updates, and removals.
POST https://api.instapage.com/v1/workspaces/{workspaceId}/team-members
- Invites multiple team members to join a workspace with specified accessLevels.PUT https://api.instapage.com/v1/workspaces/{workspaceId}/team-members
- Updates the roles of existing team members in a workspace. This endpoint allows bulk role updates for multiple team members simultaneously.DELETE https://api.instapage.com/v1/workspaces/{workspaceId}/team-members
- Remove one or more team members from a workspace. This endpoint supports bulk removal operations.
Authorization
To authorize, use this code:
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here" \
-H "Authorization: Bearer API_KEY"
await fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${API_KEY}`,
},
});
await fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${API_KEY}`,
},
});
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey
],
]);
Make sure to replace
API_KEY
with your API key.
Instapage expects for the API key to be included in all API requests to the server in a header.
Workspaces
Get All Workspaces
Retrieve all workspaces that the provided token has access to.
HTTP Request
https://api.instapage.com/v1/workspaces
curl "https://api.instapage.com/v1/workspaces?page=1" \
-H "Authorization: Bearer API_KEY"
async function fetchWorkspaces(page, apiKey) {
const response = await fetch(`https://api.instapage.com/v1/workspaces?page=${page}`, {
headers: {
'Authorization': `Bearer ${apiKey}`,
},
});
if (!response.ok) {
throw new Error(`Failed to fetch workspaces: ${response.statusText}`);
}
const data = await response.json();
return data;
}
type Workspace = {
workspaceId: number;
ownerId: number;
workspaceName: string;
accessLevel: 'owner' | 'editor' | 'manager' | 'viewer';
createdAt: number;
};
type Meta = {
page: number;
};
type WorkspacesResponse = {
data: Workspace[];
meta: Meta;
};
async function fetchWorkspaces(page: number, apiKey: string): Promise<WorkspacesResponse> {
const response = await fetch(`https://api.instapage.com/v1/workspaces?page=${page}`, {
headers: {
'Authorization': `Bearer ${apiKey}`,
},
});
if (!response.ok) {
throw new Error(`Failed to fetch workspaces: ${response.statusText}`);
}
const data: WorkspacesResponse = await response.json();
return data;
}
<?php
declare(strict_types=1);
namespace InstapageWorkspacesFetcher;
enum AccessLevel: string
{
case Owner = 'owner';
case Editor = 'editor';
case Manager = 'manager';
case Viewer = 'viewer';
}
readonly class Workspace
{
public function __construct(
public int $workspaceId,
public int $ownerId,
public string $workspaceName,
public AccessLevel $accessLevel,
public int $createdAt
) {}
public function toArray(): array
{
return [
'workspaceId' => $this->workspaceId,
'ownerId' => $this->ownerId,
'workspaceName' => $this->workspaceName,
'accessLevel' => $this->accessLevel->value,
'createdAt' => $this->createdAt
];
}
public static function fromArray(array $data): self
{
return new self(
$data['workspaceId'],
$data['ownerId'],
$data['workspaceName'],
AccessLevel::from($data['accessLevel']),
$data['createdAt']
);
}
}
readonly class Meta
{
public function __construct(
public int $page
) {}
public function toArray(): array
{
return [
'page' => $this->page
];
}
public static function fromArray(array $data): self
{
return new self($data['page']);
}
}
class WorkspacesResponse
{
/**
* @param Workspace[] $data
*/
public function __construct(
private array $data,
private Meta $meta
) {}
/**
* @return Workspace[]
*/
public function getData(): array
{
return $this->data;
}
public function getMeta(): Meta
{
return $this->meta;
}
}
class WorkspacesFetcher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function fetchWorkspaces(int $page): WorkspacesResponse
{
$url = sprintf(
'%s/v1/workspaces?page=%d',
$this->baseUrl,
$page
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to fetch workspaces: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return new WorkspacesResponse(
array_map(
fn($workspaceData) => Workspace::fromArray($workspaceData),
$responseData['data']
),
Meta::fromArray($responseData['meta'])
);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$page = 1;
$fetcher = new WorkspacesFetcher($baseUrl, $apiKey);
$workspacesResponse = $fetcher->fetchWorkspaces($page);
// Process workspaces
foreach ($workspacesResponse->getData() as $workspace) {
// Do something with each workspace
print_r($workspace->toArray());
}
// Access metadata
$meta = $workspacesResponse->getMeta();
print_r($meta->toArray());
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": [
{
"workspaceId": 1177,
"ownerId": 1319,
"workspaceName": "Personal Projects",
"accessLevel": "owner",
"createdAt": 1262304000
},
{
"workspaceId": 1801,
"ownerId": 1637,
"workspaceName": "Personal Projects",
"accessLevel": "viewer",
"createdAt": 1262304000
},
{
"workspaceId": 2637,
"ownerId": 2517,
"workspaceName": "Personal Projects",
"accessLevel": "manager",
"createdAt": 1262304000
},
{
"workspaceId": 1771,
"ownerId": 1624,
"workspaceName": "Personal Projects",
"accessLevel": "editor",
"createdAt": 1262304000
}
],
"meta": {
"pagination": {
"currentPage": 1,
"perPage": 100,
"totalItemsCount": 4,
"totalPagesCount": 1,
"nextPage": null,
"previousPage": null
}
}
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Query Parameters
Parameter | Type | Default | Description |
---|---|---|---|
page |
number |
1 |
Specifies which page to fetch. Used for pagination purposes. |
name |
string |
null |
Optional name of the workspace to limit the result. Convenient if you already know how your workspace is named. (Case insensitive) |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data[].workspaceId |
number |
Unique identifier of the workspace. |
data[].ownerId |
number |
Identifier of the workspace owner. |
data[].workspaceName |
string |
Name of the workspace. |
data[].accessLevel |
string |
User's access level to the workspace. |
data[].createdAt |
number |
Creation date of the workspace in UNIX timestamp format. |
meta.pagination.currentPage |
number |
Number of the current page of results. |
meta.pagination.perPage |
number |
Number of items per page. |
meta.pagination.totalItemsCount |
number |
Total number of items. |
meta.pagination.totalPagesCount |
number |
Total number of pages. |
meta.pagination.nextPage |
number? |
Link to the next page (null if none). |
meta.pagination.previousPage |
number? |
Link to the previous page (null if none). |
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully. |
400 |
Bad request. Validation error — review input parameters. |
401 |
Unauthorized. Authentication failed or missing credentials. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Get Single Workspace
Retrieves details of a single workspace by its ID..
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}
curl -X GET "https://api.instapage.com/v1/workspaces/{workspaceId}" \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json"
async function getWorkspace(workspaceId, apiKey) {
const response = await fetch(`https://api.instapage.com/v1/workspaces/${workspaceId}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Failed to get workspace: ${response.statusText}`);
}
const data = await response.json();
return data;
}
// Example usage
const apiKey = 'your_api_key_here';
const workspaceId = 12345;
getWorkspace(workspaceId. apiKey)
.then(workspace => {
console.log('Workspace:', workspace);
})
.catch(error => {
console.error('Error getting workspace:', error);
});
type AccessLevel = 'owner' | 'editor' | 'manager' | 'viewer';
interface Workspace {
workspaceId: number;
ownerId: number;
workspaceName: string;
accessLevel: AccessLevel;
createdAt: number;
}
class WorkspaceFetcher {
private baseUrl: string;
private apiKey: string;
constructor(baseUrl: string, apiKey: string) {
this.baseUrl = baseUrl;
this.apiKey = apiKey;
}
async getWorkspace(workspaceId: number): Promise<Workspace> {
const url = `${this.baseUrl}/v1/workspaces/${workspaceId}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Failed to get workspace: ${response.statusText}`);
}
const responseData = await response.json();
return responseData.data;
}
}
// Example usage
const baseUrl = 'https://api.instapage.com';
const apiKey = 'your_api_key_here';
const fetcher = new WorkspaceFetcher(baseUrl, apiKey);
const workspaceId = 12345;
fetcher.getWorkspace(workspaceId)
.then(workspace => {
console.log('Workspace:', workspace);
})
.catch(error => {
console.error('Error getting workspace:', error);
});
<?php
declare(strict_types=1);
namespace InstapageWorkspacesFetcher;
enum AccessLevel: string
{
case Owner = 'owner';
case Editor = 'editor';
case Manager = 'manager';
case Viewer = 'viewer';
}
readonly class Workspace
{
public function __construct(
public int $workspaceId,
public int $ownerId,
public string $workspaceName,
public AccessLevel $accessLevel,
public int $createdAt
) {}
public static function fromArray(array $data): self
{
return new self(
$data['workspaceId'],
$data['ownerId'],
$data['workspaceName'],
AccessLevel::from($data['accessLevel']),
$data['createdAt']
);
}
}
class WorkspacesFetcher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function getWorkspace(int $workspaceId): Workspace
{
$url = sprintf('%s/v1/workspaces/%d', $this->baseUrl, $workspaceId);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to fetch workspace: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return Workspace::fromArray($responseData['data']);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 12345;
$fetcher = new WorkspacesFetcher($baseUrl, $apiKey);
$workspace = $fetcher->getWorkspace($workspaceId);
echo 'Workspace retrieved: ' . json_encode($workspace, JSON_PRETTY_PRINT);
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": {
"workspaceId": 2000,
"ownerId": 1319,
"workspaceName": "New Workspace Name",
"accessLevel": "owner",
"createdAt": 1700304000
}
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to retrieve pages for |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data.workspaceId |
number |
Unique identifier of the workspace. |
data.ownerId |
number |
Identifier of the workspace owner. |
data.workspaceName |
string |
Name of the workspace. |
data.accessLevel |
string |
User's access level to the workspace. |
data.createdAt |
number |
Creation date of the workspace in UNIX timestamp format. |
Response status codes
Status | Description |
---|---|
200 |
Request was processed successfully. |
400 |
Bad request. |
401 |
Unauthorized. Authentication failed or missing credentials. |
404 |
Workspace not found. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Add New Workspace
Create a new workspace for the authenticated user.
Note: Each workspace must have a unique name under the same owner.
HTTP Request
https://api.instapage.com/v1/workspaces
curl -X POST "https://api.instapage.com/v1/workspaces" \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "New Workspace"}'
async function createWorkspace(name, apiKey) {
const response = await fetch(`https://api.instapage.com/v1/workspaces`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ name }),
});
if (!response.ok) {
throw new Error(`Failed to create workspace: ${response.statusText}`);
}
const data = await response.json();
return data;
}
type AccessLevel = 'owner' | 'editor' | 'manager' | 'viewer';
interface Workspace {
workspaceId: number;
ownerId: number;
workspaceName: string;
accessLevel: AccessLevel;
createdAt: number;
}
class WorkspaceCreator {
private baseUrl: string;
private apiKey: string;
constructor(baseUrl: string, apiKey: string) {
this.baseUrl = baseUrl;
this.apiKey = apiKey;
}
async createWorkspace(name: string): Promise<Workspace> {
const url = `${this.baseUrl}/v1/workspaces`;
const payload = JSON.stringify({ name });
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
'Content-Length': payload.length.toString(),
},
body: payload,
});
if (!response.ok) {
throw new Error(`Failed to create workspace: ${response.statusText}`);
}
const responseData = await response.json();
return responseData.data;
}
}
// Example usage
const baseUrl = 'https://api.instapage.com';
const apiKey = 'your_api_key_here';
const creator = new WorkspaceCreator(baseUrl, apiKey);
creator.createWorkspace('New Workspace Name')
.then(workspace => {
console.log('Created Workspace:', workspace);
})
.catch(error => {
console.error('Error creating workspace:', error);
});
<?php
declare(strict_types=1);
namespace InstapageWorkspacesCreator;
enum AccessLevel: string
{
case Owner = 'owner';
case Editor = 'editor';
case Manager = 'manager';
case Viewer = 'viewer';
}
readonly class Workspace
{
public function __construct(
public int $workspaceId,
public int $ownerId,
public string $workspaceName,
public AccessLevel $accessLevel,
public int $createdAt
) {}
public static function fromArray(array $data): self
{
return new self(
$data['workspaceId'],
$data['ownerId'],
$data['workspaceName'],
AccessLevel::from($data['accessLevel']),
$data['createdAt']
);
}
}
class WorkspacesCreator
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function createWorkspace(string $name): WorkspacesResponse
{
$url = sprintf(
'%s/v1/workspaces',
$this->baseUrl,
$page
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to fetch workspaces: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return Workspace::fromArray($responseData['data']);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$newWorkspaceName = 'workspace-12';
$creator = new WorkspacesCreator($baseUrl, $apiKey);
$createResponse = $creator->createWorkspace($newWorkspaceName);
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": {
"workspaceId": 2000,
"ownerId": 1319,
"workspaceName": "New Workspace Name",
"accessLevel": "owner",
"createdAt": 1700304000
}
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Request Body
Parameter | Type | Required | Description |
---|---|---|---|
name |
string |
Yes | The unique name of the workspace. |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data.workspaceId |
number |
Unique identifier of the workspace. |
data.ownerId |
number |
Identifier of the workspace owner. |
data.workspaceName |
string |
Name of the workspace. |
data.accessLevel |
string |
User's access level to the workspace. |
data.createdAt |
number |
Creation date of the workspace in UNIX timestamp format. |
Response status codes
Status | Description |
---|---|
201 |
The workspace was created successfully. |
400 |
Bad request. Validation error — review input parameters. |
401 |
Unauthorized. Authentication failed or missing credentials. |
409 |
Conflict. A workspace with the same name already exists. |
422 |
Unprocessable Entity. Limit of workspaces has been reached. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Rename Workspace
Updates the name of an existing workspace.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}
curl -X PATCH "https://api.instapage.com/v1/workspaces/{workspaceId}" \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "New Workspace Name"}'
async function renameWorkspace(workspaceId, name, apiKey) {
const response = await fetch(`https://api.instapage.com/v1/workspaces/${workspaceId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ name }),
});
if (!response.ok) {
throw new Error(`Failed to rename workspace: ${response.statusText}`);
}
const data = await response.json();
return data;
}
// Example usage
const workspaceId = 123;
const newWorkspaceName = 'Renamed Workspace';
const apiKey = 'your_api_key_here';
renameWorkspace(workspaceId, newWorkspaceName, apiKey)
.then(data => {
console.log('Renamed Workspace:', data);
})
.catch(error => {
console.error('Error renaming workspace:', error);
});
type AccessLevel = 'owner' | 'editor' | 'manager' | 'viewer';
interface Workspace {
workspaceId: number;
ownerId: number;
workspaceName: string;
accessLevel: AccessLevel;
createdAt: number;
}
class WorkspaceRenamer {
private baseUrl: string;
private apiKey: string;
constructor(baseUrl: string, apiKey: string) {
this.baseUrl = baseUrl;
this.apiKey = apiKey;
}
async renameWorkspace(workspaceId: number, newName: string): Promise<Workspace> {
const url = `${this.baseUrl}/v1/workspaces/${workspaceId}`;
const payload = JSON.stringify({ name: newName });
const response = await fetch(url, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
'Content-Length': payload.length.toString(),
},
body: payload,
});
if (!response.ok) {
throw new Error(`Failed to rename workspace: ${response.statusText}`);
}
const responseData = await response.json();
return responseData.data;
}
}
// Example usage
const baseUrl = 'https://api.instapage.com';
const apiKey = 'your_api_key_here';
const renamer = new WorkspaceRenamer(baseUrl, apiKey);
const workspaceId = 123;
const newWorkspaceName = 'Renamed Workspace';
renamer.renameWorkspace(workspaceId, newWorkspaceName)
.then(workspace => {
console.log('Renamed Workspace:', workspace);
})
.catch(error => {
console.error('Error renaming workspace:', error);
});
<?php
declare(strict_types=1);
namespace InstapageWorkspacesRenamer;
enum AccessLevel: string
{
case Owner = 'owner';
case Editor = 'editor';
case Manager = 'manager';
case Viewer = 'viewer';
}
readonly class Workspace
{
public function __construct(
public int $workspaceId,
public int $ownerId,
public string $workspaceName,
public AccessLevel $accessLevel,
public int $createdAt
) {}
public static function fromArray(array $data): self
{
return new self(
$data['workspaceId'],
$data['ownerId'],
$data['workspaceName'],
AccessLevel::from($data['accessLevel']),
$data['createdAt']
);
}
}
class WorkspacesRenamer
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function renameWorkspace(int $workspaceId, string $newName): Workspace
{
$url = sprintf('%s/v1/workspaces/%d', $this->baseUrl, $workspaceId);
$payload = json_encode(['name' => $newName]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json',
],
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_POSTFIELDS => $payload,
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to rename workspace: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return Workspace::fromArray($responseData['data']);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 123;
$newWorkspaceName = 'Renamed Workspace';
$renamer = new WorkspacesRenamer($baseUrl, $apiKey);
$updatedWorkspace = $renamer->renameWorkspace($workspaceId, $newWorkspaceName);
echo 'Workspace renamed to: ' . $updatedWorkspace->workspaceName;
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": {
"workspaceId": 2000,
"ownerId": 1319,
"workspaceName": "New Workspace Name",
"accessLevel": "owner",
"createdAt": 1700304000
}
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to update. |
Request Body
Field | Type | Description |
---|---|---|
name |
string |
The new name for the workspace. |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data.workspaceId |
number |
Unique identifier of the workspace. |
data.ownerId |
number |
Identifier of the workspace owner. |
data.workspaceName |
string |
Updated name of the workspace. |
data.accessLevel |
string |
User's access level to the workspace. |
data.createdAt |
number |
Creation date of the workspace in UNIX timestamp format. |
Response status codes
Status | Description |
---|---|
200 |
Request was processed successfully. |
400 |
Bad request. Invalid input provided. |
401 |
Unauthorized. Authentication failed or missing credentials. |
404 |
Workspace not found. |
409 |
Conflict. The workspace name is already taken. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Delete Workspace
Deletes a workspace by its ID.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}
curl -X DELETE "https://api.instapage.com/v1/workspaces/{workspaceId}" \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json"
async function deleteWorkspace(workspaceId, apiKey) {
const response = await fetch(`https://api.instapage.com/v1/workspaces/${workspaceId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Failed to delete workspace: ${response.statusText}`);
}
return response.json();
}
// Example usage
const workspaceId = 'workspaceId_here';
const apiKey = 'your_api_key_here';
deleteWorkspace(workspaceId, apiKey)
.then(data => {
console.log('Workspace deleted:', data);
})
.catch(error => {
console.error('Error deleting workspace:', error);
});
class WorkspaceDeleter {
private baseUrl: string;
private apiKey: string;
constructor(baseUrl: string, apiKey: string) {
this.baseUrl = baseUrl;
this.apiKey = apiKey;
}
async deleteWorkspace(workspaceId: string): Promise<void> {
const url = `${this.baseUrl}/v1/workspaces/${workspaceId}`;
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Failed to delete workspace: ${response.statusText}`);
}
console.log('Workspace deleted successfully');
}
}
// Example usage
const baseUrl = 'https://api.instapage.com';
const apiKey = 'your_api_key_here';
const deleter = new WorkspaceDeleter(baseUrl, apiKey);
deleter.deleteWorkspace('workspaceId_here')
.then(() => {
console.log('Workspace deleted');
})
.catch(error => {
console.error('Error deleting workspace:', error);
});
<?php
declare(strict_types=1);
namespace Instapage\PublicApi\UserInterface\Workspaces;
class WorkspaceDeleter
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function deleteWorkspace(string $workspaceId): void
{
$url = sprintf(
'%s/v1/workspaces/%s',
$this->baseUrl,
$workspaceId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
],
CURLOPT_CUSTOMREQUEST => 'DELETE'
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to delete workspace: HTTP $httpCode");
}
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 'workspaceId_here';
$deleter = new WorkspaceDeleter($baseUrl, $apiKey);
$deleter->deleteWorkspace($workspaceId);
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to delete. |
Response status codes
Status | Description |
---|---|
200 |
Workspace successfully deleted. |
400 |
Bad request. |
401 |
Unauthorized. Authentication failed or missing credentials. |
404 |
Workspace not found. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Related articles
Team Members
Get All Team Members
Retrieve all team members for a specific workspace.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/team-members
curl "https://api.instapage.com/v1/workspaces/{workspaceId}/team-members" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json"
Example of body response from request
{
"data": [
{
"userId": 4379,
"email": "example_user@airslate.com",
"invitedAt": 1685608225,
"fullName": "John Smith",
"accessLevel": "editor",
"invitationStatus": "accepted",
"lastLoginAt": 1685608226,
"lastActivityInWorkspaceAt": null
},
{
"userId": 4377,
"email": "example1_user@airslate.com",
"invitedAt": 1684489737,
"fullName": "John Smith",
"accessLevel": "manager",
"invitationStatus": "accepted",
"lastLoginAt": 1685970113,
"lastActivityInWorkspaceAt": null
},
{
"userId": 4373,
"email": "example1_user@airslate.com",
"invitedAt": null,
"fullName": "John Smith",
"accessLevel": "owner",
"invitationStatus": "accepted",
"lastLoginAt": 1729173925,
"lastActivityInWorkspaceAt": 1729520831
}
],
"meta": []
}
async function fetchTeamMembers(workspaceId, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/team-members`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch team members: ${response.statusText}`);
}
const data = await response.json();
return data;
}
type TeamMember = {
userId: number;
email: string;
invitedAt: number | null;
fullName: string;
accessLevel: string;
invitationStatus: 'accepted' | 'pending';
lastLoginAt: number | null;
lastActivityInWorkspaceAt: number | null;
};
type TeamMembersResponse = {
data: TeamMember[];
meta: any;
};
async function fetchTeamMembers(
workspaceId: number,
apiKey: string
): Promise<TeamMembersResponse> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/team-members`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch team members: ${response.statusText}`);
}
const data: TeamMembersResponse = await response.json();
return data;
}
<?php
declare(strict_types=1);
namespace InstapageTeamMembersFetcher;
enum InvitationStatus: string
{
case Accepted = 'accepted';
case Pending = 'pending';
}
readonly class TeamMember
{
public function __construct(
public int $userId,
public string $email,
public ?int $invitedAt,
public string $fullName,
public string $accessLevel,
public InvitationStatus $invitationStatus,
public ?int $lastLoginAt,
public ?int $lastActivityInWorkspaceAt
) {}
public function toArray(): array
{
return [
'userId' => $this->userId,
'email' => $this->email,
'invitedAt' => $this->invitedAt,
'fullName' => $this->fullName,
'accessLevel' => $this->accessLevel,
'invitationStatus' => $this->invitationStatus->value,
'lastLoginAt' => $this->lastLoginAt,
'lastActivityInWorkspaceAt' => $this->lastActivityInWorkspaceAt
];
}
public static function fromArray(array $data): self
{
return new self(
$data['userId'],
$data['email'],
$data['invitedAt'],
$data['fullName'],
$data['accessLevel'],
InvitationStatus::from($data['invitationStatus']),
$data['lastLoginAt'],
$data['lastActivityInWorkspaceAt']
);
}
}
class TeamMembersResponse
{
/**
* @param TeamMember[] $data
*/
public function __construct(
private array $data,
private array $meta
) {}
/**
* @return TeamMember[]
*/
public function getData(): array
{
return $this->data;
}
public function getMeta(): array
{
return $this->meta;
}
}
class TeamMembersFetcher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function fetchTeamMembers(int $workspaceId): TeamMembersResponse
{
$url = sprintf(
'%s/v1/workspaces/%d/team-members',
$this->baseUrl,
$workspaceId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to fetch team members: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return new TeamMembersResponse(
array_map(
fn($memberData) => TeamMember::fromArray($memberData),
$responseData['data']
),
$responseData['meta']
);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 1234;
$fetcher = new TeamMembersFetcher($baseUrl, $apiKey);
$teamMembersResponse = $fetcher->fetchTeamMembers($workspaceId);
// Process team members
foreach ($teamMembersResponse->getData() as $teamMember) {
// Do something with each team member
print_r($teamMember->toArray());
}
// Access metadata if needed
print_r($teamMembersResponse->getMeta());
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to retrieve team members for |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data[].userId |
number |
Unique identifier of the team member. |
data[].email |
string |
Email address of the team member. |
data[].invitedAt |
number? |
Timestamp when the team member was invited (null if owner). |
data[].fullName |
string |
Full name of the team member. |
data[].accessLevel |
string |
accessLevel of the team member (e.g., editor , manager , owner ). |
data[].invitationStatus |
string |
Status of the invitation (accepted or pending ). |
data[].lastLoginAt |
number? |
Timestamp of the team member's last login. |
data[].lastActivityInWorkspaceAt |
number? |
Timestamp of the team member's last activity in the workspace. |
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully. |
400 |
Bad request. Validation error — review input parameters. |
401 |
Unauthorized. Authentication failed or missing credentials. |
403 |
Forbidden. The user does not have the necessary permissions. |
404 |
Not Found. The requested resource could not be located. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
InvitationStatus Enum
The InvitationStatus
enum is used to represent the status of a team member's invitation.
This enum provides two possible states for a team member's invitation:
ACCEPTED
: The team member has accepted the invitation and is active in the workspace.PENDING
: The invitation has been sent but not yet accepted by the team member.
Invite Team Members
Invites multiple team members to join a workspace with specified accessLevels.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/team-members
curl -X POST \
https://api.instapage.com/v1/workspaces/{workspaceId}/team-members \
-H 'Authorization: Bearer {token}' \
-H 'Content-Type: application/json' \
-d '[
{
"email": "user1@example.com",
"accessLevel": "viewer"
},
{
"email": "user2@example.com",
"accessLevel": "manager"
}
]'
async function inviteTeamMembers(workspaceId, teamMembers, apiKey) {
const response = await fetch(
`https://api.instapage.com/v1/workspaces/${workspaceId}/team-members`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(teamMembers)
}
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(`Failed to invite team members: ${errorData.details}`);
}
return response.json();
}
// Example usage
const teamMembers = [
{ email: "user1@example.com", accessLevel: "viewer" },
{ email: "user2@example.com", accessLevel: "manager" }
];
try {
await inviteTeamMembers(workspaceId, teamMembers, apiKey);
console.log('Team members invited successfully');
} catch (error) {
console.error('Error inviting team members:', error);
}
type AccessLevel = 'viewer' | 'editor' | 'manager';
interface TeamMemberInvite {
email: string;
accessLevel: AccessLevel;
}
async function inviteTeamMembers(
workspaceId: number,
teamMembers: TeamMemberInvite[],
apiKey: string
): Promise<void> {
const response = await fetch(
`https://api.instapage.com/v1/workspaces/${workspaceId}/team-members`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(teamMembers)
}
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(`Failed to invite team members: ${errorData.details}`);
}
return response.json();
}
// Example usage
const teamMembers: TeamMemberInvite[] = [
{ email: "user1@example.com", accessLevel: "viewer" },
{ email: "user2@example.com", accessLevel: "manager" }
];
try {
await inviteTeamMembers(workspaceId, teamMembers, apiKey);
console.log('Team members invited successfully');
} catch (error) {
console.error('Error inviting team members:', error);
}
<?php
declare(strict_types=1);
namespace InstapageTeamMembers;
enum AccessLevel: string {
case Viewer = 'viewer';
case Editor = 'editor';
case Manager = 'manager';
}
readonly class TeamMemberInvite {
public function __construct(
public string $email,
public AccessLevel $accessLevel
) {}
public function toArray(): array {
return [
'email' => $this->email,
'accessLevel' => $this->accessLevel->value
];
}
}
class TeamMemberInviter {
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
/**
* @param TeamMemberInvite[] $teamMembers
*/
public function inviteTeamMembers(
int $workspaceId,
array $teamMembers
): void {
$url = sprintf(
'%s/v1/workspaces/%d/team-members',
$this->baseUrl,
$workspaceId
);
$requestBody = array_map(
fn($member) => $member->toArray(),
$teamMembers
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode($requestBody)
]);
$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($statusCode !== 201) {
$errorData = json_decode($response, true);
throw new \RuntimeException(
"Failed to invite team members: " .
($errorData['details'] ?? 'Unknown error')
);
}
}
}
// Example usage
try {
$inviter = new TeamMemberInviter(
'https://api.instapage.com',
'your_api_key_here'
);
$teamMembers = [
new TeamMemberInvite('user1@example.com', AccessLevel::Viewer),
new TeamMemberInvite('user2@example.com', AccessLevel::Manager)
];
$inviter->inviteTeamMembers(123, $teamMembers);
echo "Team members invited successfully\n";
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to invite members to |
Request Body
The request body should be an array of objects with the following structure:
Parameter | Type | Description |
---|---|---|
email |
string |
Email address of the user to invite |
accessLevel |
string |
accessLevel to assign to the user (viewer , viewer , or manager ) |
Response Status Codes
Status | Description |
---|---|
201 |
Created. The team members were successfully invited. |
400 |
Bad Request. Invalid input parameters or email format. |
401 |
Unauthorized. Authentication failed. |
403 |
Forbidden. User doesn't have permission to invite members or team member limit exceeded. |
404 |
Not Found. The workspace could not be found. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected error occurred. |
Remove Team Members
Remove one or more team members from a workspace. This endpoint supports bulk removal operations.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/team-members
curl -X DELETE \
"https://api.instapage.com/v1/workspaces/{workspaceId}/team-members" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '[
{
"email": "user1@example.com"
},
{
"email": "user2@example.com"
}
]'
Example of error response:
{
"title": "InvalidArgumentException",
"details": "Email \"owner@example.com\" can't be removed from workspace because is owner",
"meta": {
"requestedUserId": 4373,
"requestedPageId": 9910,
"requestedWorkspaceId": 7068
}
}
async function removeTeamMembers(workspaceId, emails, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/team-members`;
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(emails.map(email => ({ email })))
});
if (response.status === 201) {
console.log('Team members removed successfully');
return;
}
const errorData = await response.json();
throw new Error(`Failed to remove team members: ${errorData.details}`);
}
interface RemoveTeamMemberRequest {
email: string;
}
interface ErrorResponse {
title: string;
details: string;
meta: {
requestedUserId: number;
requestedWorkspaceId: number;
};
}
async function removeTeamMembers(
workspaceId: number,
emails: string[],
apiKey: string
): Promise<void> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/team-members`;
const request: RemoveTeamMemberRequest[] = emails.map(email => ({ email }));
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(request)
});
if (response.status === 201) {
return;
}
const errorData: ErrorResponse = await response.json();
throw new Error(`Failed to remove team members: ${errorData.details}`);
}
<?php
declare(strict_types=1);
namespace InstapageTeamMemberRemoval;
readonly class RemoveTeamMemberRequest {
public function __construct(
public string $email
) {}
public function toArray(): array {
return [
'email' => $this->email
];
}
}
readonly class ErrorResponse {
public function __construct(
public string $title,
public string $details,
public int $requestedUserId,
public int $requestedWorkspaceId
) {}
public static function fromArray(array $data): self {
return new self(
$data['title'],
$data['details'],
$data['meta']['requestedUserId'],
$data['meta']['requestedWorkspaceId']
);
}
}
class TeamMembersRemover {
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
/**
* @param string[] $emails
* @throws \RuntimeException
*/
public function removeTeamMembers(int $workspaceId, array $emails): void {
$url = sprintf(
'%s/v1/workspaces/%d/team-members',
$this->baseUrl,
$workspaceId
);
$request = array_map(
fn(string $email) => (new RemoveTeamMemberRequest($email))->toArray(),
$emails
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode($request)
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode === 201) {
return;
}
$errorData = json_decode($responseBody, true);
$error = ErrorResponse::fromArray($errorData);
throw new \RuntimeException("Failed to remove team members: {$error->details}");
}
}
// Example usage
try {
$remover = new TeamMembersRemover(
'https://api.instapage.com',
'your_api_key_here'
);
$workspaceId = 1234;
$emails = [
'user1@example.com',
'user2@example.com'
];
$remover->removeTeamMembers($workspaceId, $emails);
echo "Team members removed successfully\n";
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to remove members from |
Request Body
The request body should be an array of objects, each containing:
Parameter | Type | Description |
---|---|---|
email |
string |
Email address of the team member |
Special Cases
- If the authenticated user is in the removal list and is not the workspace owner, they will leave the workspace
- If the workspace owner's email is included in the removal list, an error will be returned
- If any email in the list doesn't belong to a team member, an error will be returned
Response Status Codes
Status | Description |
---|---|
201 |
Created. Team members were successfully removed. |
400 |
Bad Request. Invalid input parameters or attempting to remove workspace owner. |
401 |
Unauthorized. Authentication failed or missing credentials. |
403 |
Forbidden. User doesn't have necessary permissions (must be owner or manager). |
404 |
Not Found. Workspace not found. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Error Responses
The API returns error responses in the following format:
JSON Path | Type | Description |
---|---|---|
title |
string |
The type of error that occurred |
details |
string |
A human-readable description of the error |
meta.requestedUserId |
number |
ID of the user who made the request |
meta.requestedWorkspaceId |
number |
ID of the workspace involved |
Change Team Member Roles
Updates the roles of existing team members in a workspace. This endpoint allows bulk role updates for multiple team members simultaneously.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/team-members
curl -X PUT \
"https://api.instapage.com/v1/workspaces/{workspaceId}/team-members" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '[
{
"email": "user1@example.com",
"targetAccessLevel": "viewer"
},
{
"email": "user2@example.com",
"targetAccessLevel": "viewer"
}
]'
async function updateTeamMemberRoles(workspaceId, roleUpdates, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/team-members`;
const response = await fetch(url, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(roleUpdates)
});
if (response.status === 201) {
console.log('Team member roles updated successfully');
} else {
const errorData = await response.json();
throw new Error(`Failed to update roles: ${errorData.details}`);
}
}
// Example usage
const roleUpdates = [
{
email: "user1@example.com",
targetAccessLevel: "viewer"
},
{
email: "user2@example.com",
targetAccessLevel: "viewer"
}
];
try {
await updateTeamMemberRoles(workspaceId, roleUpdates, apiKey);
} catch (error) {
console.error('Error updating team member roles:', error);
}
type AccessLevel = 'viewer' | 'editor' | 'manager';
interface RoleUpdate {
email: string;
targetAccessLevel: AccessLevel;
}
interface ErrorResponse {
title: string;
details: string;
meta: {
requestedUserId: number;
requestedWorkspaceId: number;
};
}
async function updateTeamMemberRoles(
workspaceId: number,
roleUpdates: RoleUpdate[],
apiKey: string
): Promise<void> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/team-members`;
const response = await fetch(url, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(roleUpdates)
});
if (response.status === 201) {
console.log('Team member roles updated successfully');
return;
}
const errorData: ErrorResponse = await response.json();
throw new Error(`Failed to update roles: ${errorData.details}`);
}
// Example usage
const roleUpdates: RoleUpdate[] = [
{
email: "user1@example.com",
targetAccessLevel: "viewer"
},
{
email: "user2@example.com",
targetAccessLevel: "editor"
}
];
try {
await updateTeamMemberRoles(workspaceId, roleUpdates, apiKey);
} catch (error) {
console.error('Error updating team member roles:', error);
}
<?php
declare(strict_types=1);
namespace InstapageTeamMembers;
enum AccessLevel: string
{
case Viewer = 'viewer';
case Editor = 'editor';
case Manager = 'manager';
}
readonly class RoleUpdate
{
public function __construct(
public string $email,
public AccessLevel $targetAccessLevel
) {}
public function toArray(): array
{
return [
'email' => $this->email,
'targetAccessLevel' => $this->targetAccessLevel->value
];
}
}
class TeamMemberRoleUpdater
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
/**
* @param RoleUpdate[] $roleUpdates
* @throws \RuntimeException
*/
public function updateRoles(int $workspaceId, array $roleUpdates): void
{
$url = sprintf(
'%s/v1/workspaces/%d/team-members',
$this->baseUrl,
$workspaceId
);
$requestBody = array_map(
fn(RoleUpdate $update) => $update->toArray(),
$roleUpdates
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => json_encode($requestBody),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($statusCode === 201) {
return;
}
$errorData = json_decode($response, true);
throw new \RuntimeException(
sprintf('Failed to update roles: %s', $errorData['details'])
);
}
}
// Example usage
try {
$updater = new TeamMemberRoleUpdater(
'https://api.instapage.com',
'your_api_key_here'
);
$roleUpdates = [
new RoleUpdate('user1@example.com', AccessLevel::Viewer),
new RoleUpdate('user2@example.com', AccessLevel::Editor)
];
$updater->updateRoles(7068, $roleUpdates);
echo "Team member roles updated successfully\n";
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage() . "\n";
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace containing the team members |
Request Body
The request body should be an array of objects with the following structure:
Parameter | Type | Description |
---|---|---|
email |
string |
Email address of the team member to update |
targetAccessLevel |
string |
New role to assign (viewer , editor , or manager ) |
Response Status Codes
Status | Description |
---|---|
201 |
Created. The team member roles were successfully updated. |
400 |
Bad Request. Invalid input parameters or duplicate emails in request. |
401 |
Unauthorized. Authentication failed or missing credentials. |
403 |
Forbidden. The user doesn't have permission to modify roles or attempting to modify the owner's role. |
404 |
Not Found. The workspace was not found or one or more team members don't exist in the workspace. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Error Responses
The API may return error responses in the following format:
JSON Path | Type | Description |
---|---|---|
title |
string |
The type of error that occurred |
details |
string |
A human-readable description of the error |
meta.requestedUserId |
number |
ID of the user who made the request |
meta.requestedWorkspaceId |
number |
ID of the workspace involved |
Related articles
Pages
Get All Pages
Retrieve pages for a specific workspace.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/pages
curl "https://api.instapage.com/v1/workspaces/{workspaceId}/pages" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json"
The above request returns JSON structured like this:
{
"data": [
{
"id": 9399,
"title": "My published page",
"url": "mypage.example.com",
"publishStatus": "published",
"publishMethod": "customDomain",
"createdAt": 1692168365,
"updatedAt": 1725361407,
"publishedAt": 1726005213,
"isDeleted": false,
"pageType": "standard",
"totalPersonalizedExperienceCount": 6,
"isScheduled": false
},
{
"id": 9909,
"title": "My unpublished page",
"url": null,
"publishStatus": "unpublished",
"publishMethod": "customDomain",
"createdAt": 1725916359,
"updatedAt": 1725916362,
"publishedAt": 1725921862,
"isDeleted": false,
"pageType": "standard",
"totalPersonalizedExperienceCount": 0,
"isScheduled": true
}
],
"meta": {
"pagination": {
"currentPage": 1,
"perPage": 100,
"totalItemsCount": 2,
"totalPagesCount": 1,
"nextPage": null,
"previousPage": null
}
}
}
async function fetchPages(workspaceId, page, isDeleted, publishStatus, apiKey) {
const url = new URL(`https://api.instapage.com/v1/workspaces/${workspaceId}/pages`);
url.searchParams.append('page', page);
url.searchParams.append('isDeleted', isDeleted);
if (publishStatus) {
url.searchParams.append('publishStatus', publishStatus);
}
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch pages: ${response.statusText}`);
}
const data = await response.json();
return data;
}
type Page = {
id: number;
title: string;
url: string | null;
publishStatus: 'published' | 'unpublished' | 'publishedHasChanges';
publishMethod: 'cmsPlugin' | 'customDomain' | 'pageDemo';
createdAt: number;
updatedAt: number;
isDeleted: boolean;
pageType: 'amp' | 'standard' | 'collectionTemplate' | 'wordpress' | 'drupal';
totalPersonalizedExperienceCount: number;
isScheduled: boolean;
};
type PaginationMeta = {
currentPage: number;
perPage: number;
totalItemsCount: number;
totalPagesCount: number;
nextPage: number | null;
previousPage: number | null;
};
type PagesResponse = {
data: Page[];
meta: {
pagination: PaginationMeta;
};
};
async function fetchPages(
apiKey: string,
workspaceId: number,
page: number,
isDeleted: boolean,
publishStatus?: 'published' | 'unpublished' | 'publishedHasChanges',
): Promise<PagesResponse> {
const url = new URL(`https://api.instapage.com/v1/workspaces/${workspaceId}/pages`);
url.searchParams.append('page', page.toString());
url.searchParams.append('isDeleted', isDeleted.toString());
if (publishStatus) {
url.searchParams.append('publishStatus', publishStatus);
}
const response = await fetch(url.toString(), {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch pages: ${response.statusText}`);
}
const data: PagesResponse = await response.json();
return data;
}
<?php
declare(strict_types=1);
namespace InstapagePagesFetcher;
enum PublishStatus: string
{
case Published = 'published';
case Unpublished = 'unpublished';
case PublishedHasChanges = 'publishedHasChanges';
}
enum PublishMethod: string
{
case CmsPlugin = 'cmsPlugin';
case CustomDomain = 'customDomain';
case PageDemo = 'pageDemo';
}
enum PageType: string
{
case Amp = 'amp';
case Standard = 'standard';
case CollectionTemplate = 'collectionTemplate';
case WordPress = 'wordpress';
case Drupal = 'drupal';
}
readonly class Page
{
public function __construct(
public int $id,
public string $title,
public ?string $url,
public PublishStatus $publishStatus,
public PublishMethod $publishMethod,
public int $createdAt,
public int $updatedAt,
public bool $isDeleted,
public PageType $pageType,
public int $totalPersonalizedExperienceCount,
public bool $isScheduled
) {}
public function toArray(): array
{
return [
'id' => $this->id,
'title' => $this->title,
'url' => $this->url,
'publishStatus' => $this->publishStatus->value,
'publishMethod' => $this->publishMethod->value,
'createdAt' => $this->createdAt,
'updatedAt' => $this->updatedAt,
'isDeleted' => $this->isDeleted,
'pageType' => $this->pageType->value,
'totalPersonalizedExperienceCount' => $this->totalPersonalizedExperienceCount,
'isScheduled' => $this->isScheduled
];
}
}
readonly class PaginationMeta
{
public function __construct(
public int $currentPage,
public int $perPage,
public int $totalItemsCount,
public int $totalPagesCount,
public ?int $nextPage,
public ?int $previousPage
) {}
public function toArray(): array
{
return [
'currentPage' => $this->currentPage,
'perPage' => $this->perPage,
'totalItemsCount' => $this->totalItemsCount,
'totalPagesCount' => $this->totalPagesCount,
'nextPage' => $this->nextPage,
'previousPage' => $this->previousPage
];
}
}
class PagesResponse
{
/**
* @param Page[] $data
*/
public function __construct(
private array $data,
private PaginationMeta $paginationMeta
) {}
public function getData(): array
{
return $this->data;
}
public function getMeta(): PaginationMeta
{
return $this->paginationMeta;
}
}
class PagesFetcher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function fetchPages(
int $workspaceId,
int $page,
bool $isDeleted,
?PublishStatus $publishStatus = null
): PagesResponse {
$url = sprintf(
'%s/v1/workspaces/%d/pages?page=%d&isDeleted=%s%s',
$this->baseUrl,
$workspaceId,
$page,
$isDeleted ? 'true' : 'false',
$publishStatus ? '&publishStatus=' . $publishStatus->value : ''
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("API request failed with status code: $httpCode");
}
$responseData = json_decode($responseBody, true);
return new PagesResponse(
array_map(fn($pageData) => new Page(
$pageData['id'],
$pageData['title'],
$pageData['url'] ?? null,
PublishStatus::from($pageData['publishStatus']),
PublishMethod::from($pageData['publishMethod']),
$pageData['createdAt'],
$pageData['updatedAt'],
$pageData['isDeleted'],
PageType::from($pageData['pageType']),
$pageData['totalPersonalizedExperienceCount'],
$pageData['isScheduled']
), $responseData['data']),
new PaginationMeta(
$responseData['meta']['pagination']['currentPage'],
$responseData['meta']['pagination']['perPage'],
$responseData['meta']['pagination']['totalItemsCount'],
$responseData['meta']['pagination']['totalPagesCount'],
$responseData['meta']['pagination']['nextPage'],
$responseData['meta']['pagination']['previousPage']
)
);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 1234;
$fetcher = new PagesFetcher($baseUrl, $apiKey);
$pagesResponse = $fetcher->fetchPages(
workspaceId: $workspaceId,
page: 1,
isDeleted: false,
publishStatus: PublishStatus::Published
);
// Process pages
foreach ($pagesResponse->getData() as $page) {
// Do something with each page
print_r($page->toArray());
}
// Access pagination metadata
$paginationMeta = $pagesResponse->getMeta();
print_r($paginationMeta->toArray());
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to retrieve pages for |
Query Parameters
Parameter | Type | Default | Description |
---|---|---|---|
page |
number |
1 |
Specifies which page to fetch. Used for pagination purposes. |
isDeleted |
boolean |
false |
When set to true , returns only deleted pages. When false , returns only non-deleted pages. |
publishStatus |
string? |
null |
Filter pages by publish status. Possible values: published , unpublished , publishedHasChanges |
publishMethod |
string? |
null |
Filter pages by publish method. Possible values: cmsPlugin , customDomain , pageDemo |
publishedAfter |
number? |
null |
Filter pages published after the specified UNIX timestamp. |
publishedBefore |
number? |
null |
Filter pages published before the specified UNIX timestamp. |
createdAfter |
number? |
null |
Filter pages created after the specified UNIX timestamp. |
createdBefore |
number? |
null |
Filter pages created before the specified UNIX timestamp. |
This endpoint retrieves a list of pages for the specified workspace. The response includes detailed information about
each page, such as its ID, title, URL, publish status, and more. The results are paginated, and you can use the page
query parameter to navigate through the pages of results.
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data[].id |
number |
Unique identifier of the page. |
data[].title |
string |
Title of the page. |
data[].url |
string? |
URL of the page, null if unpublished. |
data[].publishStatus |
string |
Current publish status of the page (e.g., published , unpublished ). |
data[].publishMethod |
string |
Method used for publishing the page (e.g., customDomain ). |
data[].createdAt |
number |
Creation timestamp of the page (UNIX format). |
data[].updatedAt |
number |
Last update timestamp of the page (UNIX format). |
data[].publishedAt |
number? |
Timestamp of when the page was published (UNIX format), null if unpublished. |
data[].isDeleted |
boolean |
Indicates whether the page has been deleted. |
data[].pageType |
string |
Type of the page (e.g., standard ). |
data[].totalPersonalizedExperienceCount |
number |
Total count of personalized experiences for the page. |
data[].isScheduled |
boolean |
Indicates whether the page is scheduled for publication. |
meta.pagination.currentPage |
number |
Number of the current page of results. |
meta.pagination.perPage |
number |
Number of items per page. |
meta.pagination.totalItemsCount |
number |
Total number of items. |
meta.pagination.totalPagesCount |
number |
Total number of pages. |
meta.pagination.nextPage |
number? |
Number of the next page, or null if there is no next page. |
meta.pagination.previousPage |
number? |
Number of the previous page, or null if there is no previous page. |
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully. |
400 |
Bad request. Validation error — review input parameters. |
401 |
Unauthorized. Authentication failed or missing credentials. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Get Page
Retrieve detailed information about a specific page within a workspace.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/pages/{pageId}
curl "https://api.instapage.com/v1/workspaces/$workspaceId/pages/$pageId" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json"
async function fetchPageDetails(workspaceId, pageId, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/pages/${pageId}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Failed to fetch page details: ${response.statusText}`);
}
return await response.json();
}
type PublishStatus = 'published' | 'unpublished' | 'publishedHasChanges';
type PublishMethod = 'cmsPlugin' | 'customDomain' | 'pageDemo';
type PageType = 'amp' | 'standard' | 'collectionTemplate' | 'wordpress' | 'drupal';
interface PageResponse {
data: {
id: number;
title: string;
url: string | null;
publishStatus: PublishStatus;
publishMethod: PublishMethod | null;
createdAt: number;
updatedAt: number;
publishedAt: number | null;
isDeleted: boolean;
pageType: PageType;
totalPersonalizedExperienceCount: number;
isScheduled: boolean;
};
meta: Record<string, never>;
}
async function fetchPageDetails(
workspaceId: number,
pageId: number,
apiKey: string
): Promise<PageResponse> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/pages/${pageId}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Failed to fetch page details: ${response.statusText}`);
}
return await response.json();
}
<?php
declare(strict_types=1);
namespace InstapagePageFetcher;
enum PublishStatus: string {
case Published = 'published';
case Unpublished = 'unpublished';
case PublishedHasChanges = 'publishedHasChanges';
}
enum PublishMethod: string {
case CmsPlugin = 'cmsPlugin';
case CustomDomain = 'customDomain';
case PageDemo = 'pageDemo';
}
enum PageType: string {
case Amp = 'amp';
case Standard = 'standard';
case CollectionTemplate = 'collectionTemplate';
case WordPress = 'wordpress';
case Drupal = 'drupal';
}
readonly class PageDetails {
public function __construct(
public int $id,
public string $title,
public ?string $url,
public PublishStatus $publishStatus,
public ?PublishMethod $publishMethod,
public int $createdAt,
public int $updatedAt,
public ?int $publishedAt,
public bool $isDeleted,
public PageType $pageType,
public int $totalPersonalizedExperienceCount,
public bool $isScheduled
) {}
public static function fromArray(array $data): self {
return new self(
$data['id'],
$data['title'],
$data['url'],
PublishStatus::from($data['publishStatus']),
$data['publishMethod'] ? PublishMethod::from($data['publishMethod']) : null,
$data['createdAt'],
$data['updatedAt'],
$data['publishedAt'],
$data['isDeleted'],
PageType::from($data['pageType']),
$data['totalPersonalizedExperienceCount'],
$data['isScheduled']
);
}
}
class PageDetailsFetcher {
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function fetchPageDetails(int $workspaceId, int $pageId): PageDetails {
$url = sprintf(
'%s/v1/workspaces/%d/pages/%d',
$this->baseUrl,
$workspaceId,
$pageId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($statusCode !== 200) {
throw new \RuntimeException("Failed to fetch page details: HTTP $statusCode");
}
$data = json_decode($response, true);
return PageDetails::fromArray($data['data']);
}
}
// Example usage
try {
$fetcher = new PageDetailsFetcher(
'https://api.instapage.com',
'your_api_key_here'
);
$pageDetails = $fetcher->fetchPageDetails(123, 456);
var_dump($pageDetails);
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": {
"id": 9371,
"title": "My Landing Page",
"url": "landing.example.com",
"publishStatus": "published",
"publishMethod": "customDomain",
"createdAt": 1692168365,
"updatedAt": 1725361407,
"publishedAt": 1726005213,
"isDeleted": false,
"pageType": "standard",
"totalPersonalizedExperienceCount": 3,
"isScheduled": false
},
"meta": {}
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace containing the page |
pageId |
number |
The ID of the page to retrieve |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Response JSON Structure
JSON Path | Type | Description |
---|---|---|
data.id |
number |
Unique identifier of the page |
data.title |
string |
Title of the page |
data.url |
string? |
URL where the page is published (null if unpublished) |
data.publishStatus |
string |
Current publish status (published , unpublished , publishedHasChanges ) |
data.publishMethod |
string? |
Method used for publishing (cmsPlugin , customDomain , pageDemo ) |
data.createdAt |
number |
Creation timestamp (UNIX format) |
data.updatedAt |
number |
Last update timestamp (UNIX format) |
data.publishedAt |
number? |
Publication timestamp (UNIX format), null if unpublished |
data.isDeleted |
boolean |
Indicates if the page has been deleted |
data.pageType |
string |
Type of page (amp , standard , collectionTemplate , wordpress , drupal ) |
data.totalPersonalizedExperienceCount |
number |
Number of personalized experiences for this page |
data.isScheduled |
boolean |
Indicates if the page has scheduled publishing |
Response Status Codes
Status | Description |
---|---|
200 |
The request was processed successfully |
400 |
Bad request. Invalid page ID or workspace ID |
401 |
Unauthorized. Authentication failed or missing credentials |
404 |
Not Found. The page or workspace could not be found or the page does not belong to workspace |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled |
Publish a Page
Publishes a page with the specified publication method and target URL.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/pages/{pageId}/publication
curl -X POST \
https://api.instapage.com/v1/workspaces/{workspaceId}/pages/{pageId}/publication \
-H 'Authorization: Bearer {token}' \
-H 'Content-Type: application/json' \
-d '{
"targetUrl": {targetUrl},
"publicationMethod": {publicationMethod}
}'
> Example of body error from request
{
"title": "InvalidDomainException",
"details": "The provided domain is not valid",
"meta": {
"requestedUserId": 4373,
"requestedPageId": 9910,
"requestedWorkspaceId": 7068,
"requestedPublishMethod": "customDomain"
}
}
const publishPage = async (targetUrl, publicationMethod, pageId, workspaceId, token) => {
try {
const response = await fetch(`https://api.instapage.com/v1/workspaces/${workspaceId}/pages/${pageId}/publication`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
targetUrl: targetUrl,
publicationMethod: publicationMethod,
})
});
if (response.status === 202) {
console.log('Page publication request accepted');
} else {
const errorData = await response.json();
console.error('Error publishing page:', errorData);
}
} catch (error) {
console.error('An error occurred:', error);
}
};
type PluginPublicationMethod = 'wordpress' | 'drupal';
type DomainPublicationMethod = 'customDomain' | 'freeDomain';
type PublicationMethod = PluginPublicationMethod | DomainPublicationMethod;
type PublishPageBodyRequest<T extends PublicationMethod> = T extends PluginPublicationMethod
? {
targetUrl: null;
publicationMethod: T;
}
: {
targetUrl: string;
publicationMethod: T;
};
interface ErrorResponse {
title: string;
details: string;
meta: {
requestedUserId: number;
requestedPageId: number;
requestedWorkspaceId: number;
requestedPublishMethod: string;
};
}
const publishPage = async (request: PublishPageBodyRequest, pageId: number, workspaceId: number, token: string): Promise<void> => {
try {
const response = await fetch(`https://api.instapage.com/v1/workspaces/${workspaceId}/pages/${pageId}/publication`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(request)
});
if (response.status === 202) {
console.log('Page publication request accepted');
} else {
const errorData: ErrorResponse = await response.json();
console.error('Error publishing page:', errorData);
}
} catch (error) {
console.error('An error occurred:', error);
}
};
<?php
declare(strict_types=1);
namespace InstapagePagePublication;
enum PluginPublicationMethod: string
{
case WordPress = 'wordpress';
case Drupal = 'drupal';
}
enum DomainPublicationMethod: string
{
case CustomDomain = 'customDomain';
case FreeDomain = 'freeDomain';
}
class PublicationMethodValidator
{
public static function validate(string $method): bool
{
return
in_array($method, array_column(PluginPublicationMethod::cases(), 'value')) ||
in_array($method, array_column(DomainPublicationMethod::cases(), 'value'));
}
}
class PublishPageBodyRequest
{
public function __construct(
private ?string $targetUrl,
private string $publicationMethod
) {
$this->validate();
}
private function validate(): void
{
// Validate publication method
if (!PublicationMethodValidator::validate($this->publicationMethod)) {
throw new \InvalidArgumentException("Invalid publication method");
}
// Validate target URL based on publication method
$isPluginMethod = in_array(
$this->publicationMethod,
array_column(PluginPublicationMethod::cases(), 'value')
);
if ($isPluginMethod && $this->targetUrl !== null) {
throw new \InvalidArgumentException("Plugin publication method cannot have a target URL");
}
if (!$isPluginMethod && $this->targetUrl === null) {
throw new \InvalidArgumentException("Non-plugin publication method requires a target URL");
}
}
public function toArray(): array
{
return [
'targetUrl' => $this->targetUrl,
'publicationMethod' => $this->publicationMethod
];
}
}
readonly class ErrorResponse
{
public function __construct(
public string $title,
public string $details,
public int $requestedUserId,
public int $requestedPageId,
public int $requestedWorkspaceId,
public string $requestedPublishMethod
) {}
public static function fromArray(array $data): self
{
return new self(
$data['title'],
$data['details'],
$data['meta']['requestedUserId'],
$data['meta']['requestedPageId'],
$data['meta']['requestedWorkspaceId'],
$data['meta']['requestedPublishMethod']
);
}
public function toArray(): array
{
return [
'title' => $this->title,
'details' => $this->details,
'meta' => [
'requestedUserId' => $this->requestedUserId,
'requestedPageId' => $this->requestedPageId,
'requestedWorkspaceId' => $this->requestedWorkspaceId,
'requestedPublishMethod' => $this->requestedPublishMethod
]
];
}
}
class PagePublisher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function publishPage(
PublishPageBodyRequest $request,
int $pageId,
int $workspaceId
): void {
$url = sprintf(
'%s/v1/workspaces/%d/pages/%d/publication',
$this->baseUrl,
$workspaceId,
$pageId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode($request->toArray())
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode === 202) {
echo "Page publication request accepted\n";
return;
}
if ($httpCode !== 200) {
$errorData = json_decode($responseBody, true);
$errorResponse = ErrorResponse::fromArray($errorData);
throw new \RuntimeException(
"Error publishing page: " .
json_encode($errorResponse->toArray())
);
}
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 1234;
$pageId = 5678;
$publisher = new PagePublisher($baseUrl, $apiKey);
// Example for plugin publication method (no target URL)
$pluginRequest = new PublishPageBodyRequest(
targetUrl: null,
publicationMethod: PluginPublicationMethod::WordPress->value
);
$publisher->publishPage($pluginRequest, $pageId, $workspaceId);
// Example for domain publication method (with target URL)
$domainRequest = new PublishPageBodyRequest(
targetUrl: 'https://example.com',
publicationMethod: DomainPublicationMethod::CustomDomain->value
);
$publisher->publishPage($domainRequest, $pageId, $workspaceId);
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace |
pageId |
number |
The ID of the page to publish |
Request Body
Parameter | Type | Description |
---|---|---|
targetUrl |
string? |
The URL where the page will be published, if is wordpress or drupal should be null |
publicationMethod |
string |
The method of publication. Can be wordpress , drupal , customDomain , or freeDomain |
Responses
Status | Description |
---|---|
202 |
Accepted. The request has been accepted for processing. |
400 |
Bad Request. Invalid input parameters or publication method not permitted. |
401 |
Unauthorized. Authentication failed (implied by AuthMiddleware). |
403 |
Forbidden. Published pages limit exceeded or user doesn't have necessary permissions. |
404 |
Not Found. The specified page was not found. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected error occurred or publish setup not found. |
503 |
Service Unavailable. Entity-related exception occurred. |
Unpublish a Page
Unpublishes a previously published page.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/pages/{pageId}/publication
curl -X DELETE \
https://api.instapage.com/v1/workspaces/{workspaceId}/pages/{pageId}/publication \
-H 'Authorization: Bearer {token}' \
-H 'Content-Type: application/json'
Example of body error from request
{
"title": "PageIsNotPublishedException",
"details": "The page \"9910\" is not published",
"meta": {
"requestedUserId": 4373,
"requestedPageId": 9910,
"requestedWorkspaceId": 7068
}
}
const unpublishPage = async (pageId, workspaceId, token) => {
const response = await fetch(`https://api.instapage.com/v1/workspaces/${workspaceId}/pages/${pageId}/publication`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (response.status === 201) {
console.log('Page unpublished successfully');
} else {
const errorData = await response.json();
console.error('Error unpublishing page:', errorData);
}
};
interface ErrorResponse {
title: string;
details: string;
meta: {
requestedUserId: number;
requestedPageId: number;
requestedWorkspaceId: number;
};
}
const unpublishPage = async (pageId: number, workspaceId: number, token: string) => {
try {
const response = await fetch(`https://api.instapage.com/v1/workspaces/${workspaceId}/pages/${pageId}/publication`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (response.status === 201) {
console.log('Page unpublished successfully');
} else {
const errorData: ErrorResponse = await response.json();
console.error('Error unpublishing page:', errorData);
}
} catch (error) {
console.error('An error occurred:', error);
}
};
<?php
declare(strict_types=1);
namespace InstapagePageUnpublication;
readonly class ErrorResponse
{
public function __construct(
public string $title,
public string $details,
public int $requestedUserId,
public int $requestedPageId,
public int $requestedWorkspaceId
) {}
public static function fromArray(array $data): self
{
return new self(
$data['title'],
$data['details'],
$data['meta']['requestedUserId'],
$data['meta']['requestedPageId'],
$data['meta']['requestedWorkspaceId']
);
}
public function toArray(): array
{
return [
'title' => $this->title,
'details' => $this->details,
'meta' => [
'requestedUserId' => $this->requestedUserId,
'requestedPageId' => $this->requestedPageId,
'requestedWorkspaceId' => $this->requestedWorkspaceId
]
];
}
}
class PageUnpublisher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function unpublishPage(int $pageId, int $workspaceId): void
{
$url = sprintf(
'%s/v1/workspaces/%d/pages/%d/publication',
$this->baseUrl,
$workspaceId,
$pageId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode === 201) {
echo "Page unpublished successfully\n";
return;
}
if ($httpCode !== 200) {
$errorData = json_decode($responseBody, true);
$errorResponse = ErrorResponse::fromArray($errorData);
throw new \RuntimeException(
"Error unpublishing page: " .
json_encode($errorResponse->toArray())
);
}
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 1234;
$pageId = 5678;
$unpublisher = new PageUnpublisher($baseUrl, $apiKey);
$unpublisher->unpublishPage($pageId, $workspaceId);
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace |
pageId |
number |
The ID of the page to unpublish |
Responses
Status | Description |
---|---|
201 |
Created. The page was successfully unpublished. |
400 |
Bad Request. The page is not published. |
401 |
Unauthorized. Authentication failed. |
403 |
Forbidden. The user doesn't have the necessary permissions. |
404 |
Not Found. The specified page was not found. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected error occurred. |
Search Pages Globally
Search for pages across all accessible workspaces by ID, title, or URL.
HTTP Request
https://api.instapage.com/v1/pages/search
curl "https://api.instapage.com/v1/pages/search?page=1&id=9371&title=my%20page" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json"
async function searchPages(page, searchParams, apiKey) {
const url = new URL('https://api.instapage.com/v1/pages/search');
url.searchParams.append('page', page);
// Add optional search parameters
if (searchParams.id) url.searchParams.append('id', searchParams.id);
if (searchParams.title) url.searchParams.append('title', searchParams.title);
if (searchParams.url) url.searchParams.append('url', searchParams.url);
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to search pages: ${response.statusText}`);
}
return await response.json();
}
type SearchParams = {
id?: number;
title?: string;
url?: string;
};
type SearchResult = {
id: number;
workspaceId: number;
title: string;
url: string | null;
};
type SearchResponse = {
data: SearchResult[];
meta: {
requestedPageId: number | null;
requestedPageTitle: string | null;
requestedPageUrl: string | null;
pagination: {
currentPage: number;
perPage: number;
totalItemsCount: number;
totalPagesCount: number;
nextPage: number | null;
previousPage: number | null;
};
};
};
async function searchPages(
page: number,
searchParams: SearchParams,
apiKey: string
): Promise<SearchResponse> {
const url = new URL('https://api.instapage.com/v1/pages/search');
url.searchParams.append('page', page.toString());
if (searchParams.id) url.searchParams.append('id', searchParams.id.toString());
if (searchParams.title) url.searchParams.append('title', searchParams.title);
if (searchParams.url) url.searchParams.append('url', searchParams.url);
const response = await fetch(url.toString(), {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to search pages: ${response.statusText}`);
}
return await response.json();
}
<?php
declare(strict_types=1);
namespace InstapagePageSearch;
readonly class SearchParams
{
public function __construct(
public ?int $id = null,
public ?string $title = null,
public ?string $url = null
) {}
public function toQueryString(): string
{
$params = [];
if ($this->id !== null) {
$params['id'] = $this->id;
}
if ($this->title !== null) {
$params['title'] = $this->title;
}
if ($this->url !== null) {
$params['url'] = $this->url;
}
return http_build_query($params);
}
}
readonly class SearchResult
{
public function __construct(
public int $id,
public int $workspaceId,
public string $title,
public ?string $url
) {}
public static function fromArray(array $data): self
{
return new self(
$data['id'],
$data['workspaceId'],
$data['title'],
$data['url'] ?? null
);
}
}
class PageSearcher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function searchPages(int $page, SearchParams $params): array
{
$queryString = $params->toQueryString();
$url = sprintf(
'%s/v1/pages/search?page=%d&%s',
$this->baseUrl,
$page,
$queryString
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Search request failed: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return array_map(
fn($result) => SearchResult::fromArray($result),
$responseData['data']
);
}
}
// Example usage
try {
$searcher = new PageSearcher(
'https://api.instapage.com',
'your_api_key_here'
);
$params = new SearchParams(
title: 'Landing Page'
);
$results = $searcher->searchPages(1, $params);
foreach ($results as $result) {
echo sprintf(
"Found page: %s (ID: %d, Workspace: %d)\n",
$result->title,
$result->id,
$result->workspaceId
);
}
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": [
{
"id": 9371,
"workspaceId": 7068,
"title": "My Landing Page",
"url": "landing.example.com"
},
{
"id": 9372,
"workspaceId": 7068,
"title": "Product Launch Page",
"url": null
}
],
"meta": {
"requestedPageId": null,
"requestedPageTitle": "page",
"requestedPageUrl": null,
"pagination": {
"currentPage": 1,
"perPage": 100,
"totalItemsCount": 2,
"totalPagesCount": 1,
"nextPage": null,
"previousPage": null
}
}
}
Query Parameters
Parameter | Type | Default | Description |
---|---|---|---|
page |
number |
1 |
Page number for pagination. |
id |
number |
null |
Filter results by page ID. |
title |
string |
null |
Filter results by page title (case-insensitive). |
url |
string |
null |
Filter results by published URL. |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data[].id |
number |
Unique identifier of the page. |
data[].workspaceId |
number |
ID of the workspace containing the page. |
data[].title |
string |
Title of the page. |
data[].url |
string? |
Published URL of the page (null if unpublished). |
meta.requestedPageId |
number? |
The page ID used in the search request. |
meta.requestedPageTitle |
string? |
The page title used in the search request. |
meta.requestedPageUrl |
string? |
The URL used in the search request. |
meta.pagination.currentPage |
number |
Current page number. |
meta.pagination.perPage |
number |
Number of results per page. |
meta.pagination.totalItemsCount |
number |
Total number of results found. |
meta.pagination.totalPagesCount |
number |
Total number of pages available. |
meta.pagination.nextPage |
number? |
Next page number, null if no more pages. |
meta.pagination.previousPage |
number? |
Previous page number, null if on first page. |
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully. |
400 |
Bad request. Invalid parameters provided. |
401 |
Unauthorized. Authentication failed or missing credentials. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Related articles
- Publishing options
- Creating a new page
- How do I publish my page to my own domain
- Publishing Your Page to Drupal
- Publishing through WordPress.org
- Troubleshooting WordPress or Drupal publishing
Personalizations
Get All Personalizations
Retrieve all personalizations for a specific page.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/pages/{pageId}/personalizations
curl "https://api.instapage.com/v1/workspaces/{workspaceId}/pages/{pageId}/personalizations" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json"
Example of body response from request
{
"data": [
{
"pageId": 9402,
"personalizationId": "108b2b17-478d-4f8f-9059-003d44a89b39",
"title": "example page",
"publishStatus": "published",
"createdAt": 1696332561,
"url": "ip.example.com?108b2b17=003d44a89b39&id-param=example-page",
"publishMethod": "customDomain",
"isDefaultPersonalization": false,
"isScheduled": false
},
{
"pageId": 9399,
"personalizationId": "18d22df0-7198-48ab-8301-9c110f71d667",
"title": "default example page",
"publishStatus": "published",
"createdAt": 1692168365,
"url": "ip.example.com",
"publishMethod": "customDomain",
"isDefaultPersonalization": true,
"isScheduled": false
}
],
"meta": {
"pagination": {
"currentPage": 1,
"perPage": 100,
"totalItemsCount": 2,
"totalPagesCount": 1,
"nextPage": null,
"previousPage": null
}
}
}
async function fetchPersonalizations(workspaceId, pageId, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/pages/${pageId}/personalizations`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch personalizations: ${response.statusText}`);
}
const data = await response.json();
return data;
}
type Personalization = {
pageId: number;
personalizationId: string;
title: string;
publishStatus: 'published' | 'unpublished';
createdAt: number;
url: string | null;
publishMethod: string;
isDefaultPersonalization: boolean;
};
type PaginationMeta = {
current_page: number;
per_page: number;
total_items_count: number;
total_pages_count: number;
next_page: number | null;
previous_page: number | null;
};
type PersonalizationsResponse = {
data: Personalization[];
meta: {
pagination: PaginationMeta;
};
};
async function fetchPersonalizations(
workspaceId: number,
pageId: number,
apiKey: string
): Promise<PersonalizationsResponse> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/pages/${pageId}/personalizations`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch personalizations: ${response.statusText}`);
}
const data: PersonalizationsResponse = await response.json();
return data;
}
<?php
declare(strict_types=1);
namespace InstapagePersonalizationsFetcher;
enum PublishStatus: string
{
case Published = 'published';
case Unpublished = 'unpublished';
}
readonly class Personalization
{
public function __construct(
public int $pageId,
public string $personalizationId,
public string $title,
public PublishStatus $publishStatus,
public int $createdAt,
public ?string $url,
public string $publishMethod,
public bool $isDefaultPersonalization
) {}
public function toArray(): array
{
return [
'pageId' => $this->pageId,
'personalizationId' => $this->personalizationId,
'title' => $this->title,
'publishStatus' => $this->publishStatus->value,
'createdAt' => $this->createdAt,
'url' => $this->url,
'publishMethod' => $this->publishMethod,
'isDefaultPersonalization' => $this->isDefaultPersonalization
];
}
public static function fromArray(array $data): self
{
return new self(
$data['pageId'],
$data['personalizationId'],
$data['title'],
PublishStatus::from($data['publishStatus']),
$data['createdAt'],
$data['url'] ?? null,
$data['publishMethod'],
$data['isDefaultPersonalization']
);
}
}
readonly class PaginationMeta
{
public function __construct(
public int $currentPage,
public int $perPage,
public int $totalItemsCount,
public int $totalPagesCount,
public ?int $nextPage,
public ?int $previousPage
) {}
public function toArray(): array
{
return [
'current_page' => $this->currentPage,
'per_page' => $this->perPage,
'total_items_count' => $this->totalItemsCount,
'total_pages_count' => $this->totalPagesCount,
'next_page' => $this->nextPage,
'previous_page' => $this->previousPage
];
}
public static function fromArray(array $data): self
{
return new self(
$data['current_page'],
$data['per_page'],
$data['total_items_count'],
$data['total_pages_count'],
$data['next_page'],
$data['previous_page']
);
}
}
class PersonalizationsResponse
{
/**
* @param Personalization[] $data
*/
public function __construct(
private array $data,
private PaginationMeta $paginationMeta
) {}
public function getData(): array
{
return $this->data;
}
public function getMeta(): PaginationMeta
{
return $this->paginationMeta;
}
}
class PersonalizationsFetcher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function fetchPersonalizations(
int $workspaceId,
int $pageId
): PersonalizationsResponse {
$url = sprintf(
'%s/v1/workspaces/%d/pages/%d/personalizations',
$this->baseUrl,
$workspaceId,
$pageId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to fetch personalizations: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return new PersonalizationsResponse(
array_map(
fn($personalizationData) => Personalization::fromArray($personalizationData),
$responseData['data']
),
PaginationMeta::fromArray($responseData['meta']['pagination'])
);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 1234;
$pageId = 5678;
$fetcher = new PersonalizationsFetcher($baseUrl, $apiKey);
$personalizationsResponse = $fetcher->fetchPersonalizations($workspaceId, $pageId);
// Process personalizations
foreach ($personalizationsResponse->getData() as $personalization) {
// Do something with each personalization
print_r($personalization->toArray());
}
// Access pagination metadata
$paginationMeta = $personalizationsResponse->getMeta();
print_r($paginationMeta->toArray());
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace |
pageId |
number |
The ID of the page to retrieve personalizations for |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data[].pageId |
number |
Unique identifier of the page. |
data[].personalizationId |
string |
Unique identifier for the personalization experience. |
data[].title |
string |
Title of the page. |
data[].publishStatus |
string |
Current publish status of the page (e.g., published ). |
data[].createdAt |
number |
Creation timestamp of the page (UNIX format). |
data[].url |
string |
URL where the page is published. |
data[].publishMethod |
string |
Method used for publishing the page (e.g., customDomain ). |
data[].isDefaultPersonalization |
boolean |
Indicates whether this is the default personalization experience. |
data[].isScheduled |
boolean |
Indicates whether the page is scheduled for publication. |
meta.pagination.currentPage |
number |
Number of the current page of results. |
meta.pagination.perPage |
number |
Number of items per page. |
meta.pagination.totalItemsCount |
number |
Total number of items. |
meta.pagination.totalPagesCount |
number |
Total number of pages. |
meta.pagination.nextPage |
number? |
Number of the next page, or null if there is no next page. |
meta.pagination.previousPage |
number? |
Number of the previous page, or null if there is no previous page. |
This endpoint retrieves all personalizations for the specified page. The response includes detailed information about each personalization, such as its ID, title, publish status, and URL. The results are paginated, and you can use the pagination metadata to navigate through the pages of results if necessary.
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully. |
400 |
Bad request. Validation error — review input parameters. |
401 |
Unauthorized. Authentication failed or missing credentials. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Analytics
Get statistical data
Retrieve statistical data related to pages and experiences in a bulk.
HTTP Request
https://api.instapage.com/v1/workspaces/:workspaceId/analytics
curl "https://api.instapage.com/v1/workspaces/$workspaceId/analytics" \
-H "Authorization: Bearer $API_KEY"
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
--data '{
"visited": 0,
"pages": [
20476657,
10716956,
10842011
],
"timeframe": {
"start": 0,
"end": 1726150655561
},
"grouping": ["pageId"],
"interval": "yearly"
}'
async function fetchAnalytics(workspaceId, options, apiKey) {
const url =`https://api.instapage.com/v1/workspaces/${workspaceId}/analytics`;
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(options),
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
},
});
if (!response.ok) {
throw new Error(`Failed to fetch workspaces: ${response.statusText}`);
}
const data = await response.json();
return data;
}
type AnalyticsFetchOptions = {
pages: number[];
interval: 'daily' | 'hourly' | 'monthly' | 'yearly';
grouping?: ('pageId' | 'variationId')[];
timeframe?: {
start: number;
end: number;
};
visited?: number;
device?: 'any' | 'desktop' | 'mobile';
};
type AnalyticsFetchResponse = {
data: {
key: {
pageId?: number;
date?: number;
variationId?: number;
};
visit: number;
conversion: number;
leads: number;
}[];
};
async function fetchAnalytics(workspaceId: number, options: AnalyticsFetchOptions, apiKey: string) {
const url =`https://api.instapage.com/v1/workspaces/${workspaceId}/analytics`;
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(options),
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
},
});
if (!response.ok) {
throw new Error(`Failed to fetch workspaces: ${response.statusText}`);
}
const data = await response.json();
return data as AnalyticsFetchResponse;
}
<?php
declare(strict_types=1);
namespace InstapageAnalytics;
class AnalyticsFetchOptions
{
public function __construct(
public readonly array $pages,
public readonly string $interval,
public readonly ?array $grouping = null,
public readonly ?array $timeframe = null,
public readonly ?int $visited = null,
public readonly ?string $device = null
) {}
public function toArray(): array
{
$options = [
'pages' => $this->pages,
'interval' => $this->interval,
];
if ($this->grouping !== null) {
$options['grouping'] = $this->grouping;
}
if ($this->timeframe !== null) {
$options['timeframe'] = $this->timeframe;
}
if ($this->visited !== null) {
$options['visited'] = $this->visited;
}
if ($this->device !== null) {
$options['device'] = $this->device;
}
return $options;
}
}
class AnalyticsFetchResponse
{
public function __construct(
public readonly array $data
) {}
public static function fromArray(array $responseData): self
{
return new self($responseData);
}
}
class InstapageAnalyticsFetcher
{
public function __construct(
private readonly string $baseUrl,
private readonly string $apiKey
) {}
public function fetchAnalytics(
int $workspaceId,
AnalyticsFetchOptions $options
): AnalyticsFetchResponse {
$url = sprintf(
'%s/v1/workspaces/%d/analytics',
$this->baseUrl,
$workspaceId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->apiKey
],
CURLOPT_POSTFIELDS => json_encode($options->toArray(), JSON_THROW_ON_ERROR)
]);
$responseBody = curl_exec($ch);
if ($responseBody === false) {
throw new \RuntimeException('Curl request failed: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode < 200 || $httpCode >= 300) {
throw new \RuntimeException(sprintf(
'API request failed with status code %d: %s',
$httpCode,
$responseBody
));
}
$responseData = json_decode($responseBody, true, 512, JSON_THROW_ON_ERROR);
return AnalyticsFetchResponse::fromArray($responseData);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$fetcher = new InstapageAnalyticsFetcher($apiKey, $baseUrl);
$options = new AnalyticsFetchOptions(
pages: [1, 2, 3],
interval: 'daily',
grouping: ['date'],
timeframe: [
'start' => time() - 30 * 24 * 60 * 60, // 30 days ago
'end' => time()
]
);
$response = $fetcher->fetchAnalytics(123, $options);
print_r($response->data);
} catch (\JsonException $e) {
// Handle JSON encoding/decoding errors
echo "JSON Error: " . $e->getMessage();
} catch (\RuntimeException $e) {
// Handle API request errors
echo "API Request Error: " . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": [
{
"key": {
"pageId": 10842011,
"date": 1727275000
},
"visit": 42,
"conversion": 5,
"leads": 5
},
{
"key": {
"pageId": 10716956,
"date": 1727276000
},
"visit": 1,
"conversion": 1,
"leads": 1
},
{
"key": {
"pageId": 10716956,
"date": 1727277000
},
"visit": 1,
"conversion": 0,
"leads": 0
},
{
"key": {
"pageId": 10842011,
"date": 1727278000
},
"visit": 181,
"conversion": 0,
"leads": 0
}
]
}
The key depends on grouping used and will behave differently for different grouping requests.
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
Specifies which workspace to use. |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Body Parameters
Content-type should be of type application/json
.
JSON Path | Type | Default | Description |
---|---|---|---|
pages |
number[] |
null |
Specifies the pages for which the API should return statistical data. Note: You can provide up to 100 page IDs at once. |
interval |
string |
monthly |
Specifies the time interval for aggregating data. Options include daily , hourly , monthly , or yearly . |
device |
string |
any |
Determines the device type filter. Can be set to any , desktop , or mobile visits. |
timeframe.start |
number |
0 |
Defines the starting timestamp (in seconds) for fetching data. |
timeframe.end |
number |
'current time' |
Defines the ending timestamp (in seconds) for the data retrieval period. |
traffic |
string |
blended |
Specifies the type of traffic to include: blended , organic , or paid . |
grouping |
string[] |
[] |
Defines additional grouping for the data. Options include pageId and variationId . |
visited |
number |
null |
Filters data based on unique actions. A value of 1 includes only returning visitors; a value of 0 includes only unique actions. |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data[].key |
Object |
Object containing unique identifiers. Structure varies based on the request. |
data[].key.pageId |
number (optional) |
Page ID, part of the key, optional - reflects grouping of request. |
data[].key.date |
number (optional) |
Date in UNIX timestamp (seconds), part of the key, optional - reflects grouping of request. |
data[].key.variationId |
number (optional) |
Variation ID, part of the key, optional - reflects grouping of request. |
data[].visit |
number |
Total number of visits associated with the key. |
data[].conversion |
number |
Total number of conversions associated with the key. |
data[].leads |
number |
Total number of leads associated with the key. |
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully. |
400 |
Bad request. Validation error — review input parameters. |
401 |
Unauthorized. Authentication failed or missing credentials. |
403 |
Forbidden. The user does not have the necessary permissions. |
404 |
Not Found. The requested resource could not be located. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Related articles
Form Submissions
Form submissions refer to the data collected when a user successfully fills out and submits a form on your landing page.
Retrieve Form Submissions
Fetch form submission data from specified pages, with optional filtering by time range.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/submissions
curl "https://api.instapage.com/v1/workspaces/7068/submissions" \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
--data '{"pages": [9371, 9370], "timeframe": {
"start": 1717259412,
"end": 1727251907
}
}'
async function fetchSubmissions(workspaceId, pages, timerange, nextPageToken, apiKey) {
const url = new URL(`https://api.instapage.com/v1/workspaces/${workspaceId}/submissions`);
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify({ pages, ...timerange ? { timerange } : null, nextPageToken })
});
if (!response.ok) {
throw new Error(`Failed to fetch pages: ${response.statusText}`);
}
const data = await response.json();
return data;
}
type Filters = {
pages: number[];
timerange?: {
start: number;
end: number;
};
nextPageToken?: string;
};
type Submission = {
id: string;
pageId: number;
variationName: string;
variationCustomName: string;
createdAt: number;
fields: Record<string, string>;
}
type SubmissionsResponse = {
data: Submission[];
meta: {
nextPageToken: string | null;
limit: number;
};
};
async function fetchFormSubmissions(
apiKey: string,
workspaceId: number;
filters: Options;
): Promise<SubmissionsResponse> {
const url = new URL(`https://api.instapage.com/v1/workspaces/${workspaceId}/pages`);
const json = JSON.stringify(filters);
const response = await fetch(url.toString(), {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
method: 'POST',
body: json,
});
if (!response.ok) {
throw new Error(`Failed to fetch submissions: ${response.statusText}`);
}
const data: SubmissionsResponse = await response.json();
return data;
}
<?php
declare(strict_types=1);
namespace InstapageSubmissionsFetcher;
readonly class ApiConfig
{
public function __construct(
public string $baseUrl,
public string $apiKey,
public int $workspaceId
) {}
}
readonly class Filters
{
public function __construct(
private array $pages,
private ?array $timerange = null,
private ?string $nextPageToken = null
) {}
public function toArray(): array
{
$filters = ['pages' => $this->pages];
if ($this->timerange !== null) {
$filters['timerange'] = $this->timerange;
}
if ($this->nextPageToken !== null) {
$filters['nextPageToken'] = $this->nextPageToken;
}
return $filters;
}
}
class Submission
{
public function __construct(
private string $id,
private int $pageId,
private string $variationName,
private string $variationCustomName,
private int $createdAt,
private array $fields
) {}
public function toArray(): array
{
return [
'id' => $this->id,
'pageId' => $this->pageId,
'variationName' => $this->variationName,
'variationCustomName' => $this->variationCustomName,
'createdAt' => $this->createdAt,
'fields' => $this->fields
];
}
}
class SubmissionsResponse
{
public function __construct(
private array $data,
private ?string $nextPageToken,
private int $limit
) {}
public function getData(): array
{
return $this->data;
}
public function getNextPageToken(): ?string
{
return $this->nextPageToken;
}
public function getLimit(): int
{
return $this->limit;
}
}
class SubmissionsFetcher
{
public function __construct(private ApiConfig $apiConfig) {}
public function fetchFormSubmissions(Filters $filters): SubmissionsResponse
{
$url = sprintf(
'%s/v1/workspaces/%d/pages',
$this->apiConfig->baseUrl,
$this->apiConfig->workspaceId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiConfig->apiKey,
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode($filters->toArray())
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("API request failed with status code: $httpCode");
}
$responseData = json_decode($responseBody, true);
return new SubmissionsResponse(
array_map(fn($submissionData) => new Submission(
$submissionData['id'],
$submissionData['pageId'],
$submissionData['variationName'],
$submissionData['variationCustomName'],
$submissionData['createdAt'],
$submissionData['fields']
), $responseData['data']),
$responseData['meta']['nextPageToken'] ?? null,
$responseData['meta']['limit']
);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 1234;
$apiConfig = new ApiConfig($baseUrl, $apiKey, $workspaceId);
$fetcher = new SubmissionsFetcher($apiConfig);
$filters = new Filters(
pages: [1, 2, 3],
timerange: ['start' => time() - 86400, 'end' => time()],
nextPageToken: null
);
$submissionsResponse = $fetcher->fetchFormSubmissions($filters);
// Process submissions
foreach ($submissionsResponse->getData() as $submission) {
// Do something with each submission
print_r($submission->toArray());
}
// Check for next page
$nextPageToken = $submissionsResponse->getNextPageToken();
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"meta": {
"limit": 100,
"nextPageToken": "6672e0f595fd7364f4c8973f"
},
"data": {
"submissions": [
{
"id": "66797c440bf4f63b67fd1054",
"pageId": 9371,
"variationName": "A",
"variationCustomName": "A",
"createdAt": 1727261810,
"fields": {
"form-field-1": "value-of-form",
}
},
{
"id": "66797c3e0bf4f63b67fd1053",
"pageId": 9371,
"variationName": "A",
"variationCustomName": "A",
"createdAt": 1727261811,
"fields": {
"Email": "email@example.com",
}
},
{
"id": "66795e1323047c1af4cca224",
"pageId": 9370,
"variationName": "A",
"variationCustomName": "A",
"createdAt": 0,
"fields": {
"Name": "xdxd",
}
},
{
"id": "6672e0f595fd7364f4c8973f",
"pageId": 9370,
"variationName": "A",
"variationCustomName": "A",
"createdAt": 1727261813,
"fields": {
"Email": "customer1@example.com",
}
}
]
}
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to retrieve submissions for |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Body Parameters
JSON Path | Type | Default | Description |
---|---|---|---|
pages |
number[] |
[] |
A list of page IDs to filter form submissions. Note: You can provide up to 100 page IDs at once. |
timeframe.start |
number |
null |
Defines the start of the time range for filtering leads, specified in seconds. |
timeframe.end |
number |
null |
Defines the end of the time range for filtering leads, specified in seconds. |
nextPageToken |
string |
null |
Token for pagination; retrieves the next set of form submissions when provided. |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data[].id |
string |
Unique identifier for the submission. |
data[].pageId |
number |
ID of the page related to the submission. |
data[].variationName |
string |
Name of the variation used for the submission. |
data[].variationCustomName |
string |
Custom name of the variation used for the submission. |
data[].createdAt |
number |
Timestamp (in UNIX seconds) of when the submission was created. |
data[].fields |
Object |
Key-value pairs representing submission fields. |
meta.nextPageToken |
string? |
Token for fetching the next page of submissions, or null if there is no next page. |
meta.limit |
number |
Maximum number of submissions returned per page. |
This endpoint allows retrieval of form submissions from multiple pages in a single request. The data limit is capped at 100 submissions per page. To retrieve additional pages, use the nextPageToken
.
When the number of retrieved submissions is less than the limit, an empty array is returned, or nextPageToken
is null
, it indicates that no further submissions are available from the endpoint.
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully. |
400 |
Bad request. Some filter parameters are most likely not valid. |
401 |
Unauthorized. Authentication failed or missing credentials. |
403 |
Forbidden. The user does not have the necessary permissions. |
404 |
Not Found. The requested resource could not be located. |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time. |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled. |
Related articles
Experiments
Get All Experiments
Retrieve all experiments for a specific workspace with optional filtering by status.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/experiments
curl "https://api.instapage.com/v1/workspaces/$workspaceId/experiments?status[]=DRAFT&status[]=ENDED&page=1" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json"
async function fetchExperiments(workspaceId, statuses, page, apiKey) {
const url = new URL(`https://api.instapage.com/v1/workspaces/${workspaceId}/experiments`);
if (statuses && statuses.length) {
statuses.forEach(status => url.searchParams.append('status[]', status));
}
if (page) {
url.searchParams.append('page', page);
}
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch experiments: ${response.statusText}`);
}
return await response.json();
}
type ExperimentType = 'Manual' | 'AI';
type ExperimentStatus = 'DRAFT' | 'RUNNING' | 'ENDED' | 'ARCHIVED';
type Experiment = {
experimentId: number;
experimentName: string;
pageId: number;
publishedPageUrl: string;
experimentType: ExperimentType;
experimentStatus: ExperimentStatus;
createdAt: number;
startedAt: number | null;
endedAt: number | null;
createdBy: number;
};
type PaginationMeta = {
currentPage: number;
perPage: number;
totalItemsCount: number;
totalPagesCount: number;
nextPage: number | null;
previousPage: number | null;
};
type ExperimentsResponse = {
data: Experiment[];
meta: {
pagination: PaginationMeta;
};
};
async function fetchExperiments(
workspaceId: number,
apiKey: string,
statuses?: ExperimentStatus[],
page?: number,
): Promise<ExperimentsResponse> {
const url = new URL(`https://api.instapage.com/v1/workspaces/${workspaceId}/experiments`);
if (statuses?.length) {
statuses.forEach(status => url.searchParams.append('status[]', status));
}
if (page) {
url.searchParams.append('page', page);
}
const response = await fetch(url.toString(), {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch experiments: ${response.statusText}`);
}
return await response.json();
}
<?php
declare(strict_types=1);
namespace InstapageExperimentsFetcher;
enum ExperimentType: string
{
case MANUAL = 'Manual';
case AI = 'AI';
}
enum ExperimentStatus: string
{
case DRAFT = 'DRAFT';
case RUNNING = 'RUNNING';
case ENDED = 'ENDED';
case ARCHIVED = 'ARCHIVED';
}
readonly class Experiment
{
public function __construct(
public int $experimentId,
public string $name,
public int $pageId,
public string $publishedPageUrl,
public ExperimentType $type,
public ExperimentStatus $status,
public int $createdAt,
public int $createdBy,
public ?int $startedAt,
public ?int $endedAt
) {}
public static function fromArray(array $data): self
{
return new self(
$data['experimentId'],
$data['experimentName'],
$data['pageId'],
$data['publishedPageUrl'],
ExperimentType::from($data['experimentType']),
ExperimentStatus::from($data['experimentStatus']),
$data['createdAt'],
$data['createdBy'],
$data['startedAt'],
$data['endedAt']
);
}
}
class ExperimentsFetcher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
/**
* @param ExperimentStatus[] $statuses
*/
public function fetchExperiments(
int $workspaceId,
array $statuses = [],
int $page = 1
): array {
$url = sprintf(
'%s/v1/workspaces/%d/experiments',
$this->baseUrl,
$workspaceId
);
$queryParams = ['page' => $page];
if (!empty($statuses)) {
$queryParams['status'] = array_map(fn($status) => $status->value, $statuses);
}
$url .= '?' . http_build_query($queryParams, '', '&', PHP_QUERY_RFC3986);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("API request failed with status $httpCode");
}
$data = json_decode($response, true);
return array_map(fn($item) => Experiment::fromArray($item), $data['data']);
}
}
The above request returns JSON structured like this:
{
"data": [
{
"experimentId": 8,
"experimentName": "example-experiment-ab",
"pageId": 9399,
"publishedPageUrl": "example-page-ab.pagedemo.co",
"experimentType": "Manual",
"experimentStatus": "ENDED",
"createdAt": 1695820734,
"createdBy": 1234,
"startedAt": 1696346707,
"endedAt": 1728330460
},
{
"experimentId": 11,
"experimentName": "example-experiment-ai",
"pageId": 9389,
"publishedPageUrl": "example-page-ai.pagedemo.co",
"experimentType": "AI",
"experimentStatus": "DRAFT",
"createdAt": 1695827954,
"createdBy": 1234,
"startedAt": null,
"endedAt": null
}
],
"meta": {
"pagination": {
"currentPage": 1,
"perPage": 100,
"totalItemsCount": 2,
"totalPagesCount": 1,
"nextPage": null,
"previousPage": null
}
}
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to retrieve experiments for |
Query Parameters
Parameter | Type | Default | Description |
---|---|---|---|
status[] |
string[] |
[] |
Filter experiments by status. Can include multiple values: DRAFT , RUNNING , ENDED , or ARCHIVED |
page |
number |
1 |
Page number for pagination |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Response JSON Structure
JSON Path | Type | Description |
---|---|---|
data[].experimentId |
number |
Unique identifier for the experiment |
data[].experimentName |
string |
Name of the experiment |
data[].pageId |
number |
ID of the page associated with the experiment |
data[].publishedPageUrl |
string |
URL where the experiment page is published |
data[].experimentType |
string |
Type of experiment: Manual or AI |
data[].experimentStatus |
string |
Current status: DRAFT , RUNNING , ENDED , or ARCHIVED |
data[].createdAt |
number |
Creation timestamp (UNIX format) |
data[].createdBy |
number |
user ID of the experiment creator |
data[].startedAt |
number? |
Start timestamp (UNIX format), null if not started |
data[].endedAt |
number? |
End timestamp (UNIX format), null if not ended |
meta.pagination.currentPage |
number |
Current page number |
meta.pagination.perPage |
number |
Number of items per page |
meta.pagination.totalItemsCount |
number |
Total number of items |
meta.pagination.totalPagesCount |
number |
Total number of pages |
meta.pagination.nextPage |
number? |
Next page number, null if no next page |
meta.pagination.previousPage |
number? |
Previous page number, null if no previous page |
Response Status Codes
Status | Description |
---|---|
200 |
The request was processed successfully |
400 |
Bad request - Invalid status value or pagination parameters |
401 |
Unauthorized - Authentication failed or missing credentials |
404 |
Not Found - The requested workspace was not found |
429 |
Too Many Requests - The server is rejecting requests due to excessive rate of requests |
500 |
Internal Server Error - An unexpected condition prevented the request from being fulfilled |
Related Articles
- AI Experiments
- Settings - AI Experiments
- How do I run an experiment? (A/B testing)
- How can I keep only one variation live?
- What is a control variation?
Groups
Get All Groups
Retrieve all groups (folders) for a specific workspace.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/groups
curl "https://api.instapage.com/v1/workspaces/{workspaceId}/groups" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json"
async function fetchGroups(workspaceId, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/groups`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch groups: ${response.statusText}`);
}
return await response.json();
}
type Group = {
id: number;
name: string;
pages: number[];
};
type PaginationMeta = {
currentPage: number;
perPage: number;
totalItemsCount: number;
totalPagesCount: number;
nextPage: number | null;
previousPage: number | null;
};
type GroupsResponse = {
data: Group[];
meta: {
workspaceId: number;
pagination: PaginationMeta;
};
};
async function fetchGroups(
workspaceId: number,
apiKey: string
): Promise<GroupsResponse> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/groups`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
});
if (!response.ok) {
throw new Error(`Failed to fetch groups: ${response.statusText}`);
}
return await response.json();
}
<?php
declare(strict_types=1);
namespace InstapageGroupsFetcher;
readonly class Group
{
public function __construct(
public int $id,
public string $name,
public array $pages
) {}
public static function fromArray(array $data): self
{
return new self(
$data['id'],
$data['name'],
$data['pages'] ?? []
);
}
public function toArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'pages' => $this->pages
];
}
}
readonly class PaginationMeta
{
public function __construct(
public int $currentPage,
public int $perPage,
public int $totalItemsCount,
public int $totalPagesCount,
public ?int $nextPage,
public ?int $previousPage
) {}
public static function fromArray(array $data): self
{
return new self(
$data['currentPage'],
$data['perPage'],
$data['totalItemsCount'],
$data['totalPagesCount'],
$data['nextPage'],
$data['previousPage']
);
}
}
class GroupsResponse
{
/**
* @param Group[] $data
*/
public function __construct(
private array $data,
private int $workspaceId,
private PaginationMeta $paginationMeta
) {}
/**
* @return Group[]
*/
public function getData(): array
{
return $this->data;
}
public function getWorkspaceId(): int
{
return $this->workspaceId;
}
public function getPaginationMeta(): PaginationMeta
{
return $this->paginationMeta;
}
}
class GroupsFetcher
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function fetchGroups(int $workspaceId): GroupsResponse
{
$url = sprintf(
'%s/v1/workspaces/%d/groups',
$this->baseUrl,
$workspaceId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to fetch groups: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return new GroupsResponse(
array_map(
fn($groupData) => Group::fromArray($groupData),
$responseData['data']
),
$responseData['meta']['workspaceId'],
PaginationMeta::fromArray($responseData['meta']['pagination'])
);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 7068;
$fetcher = new GroupsFetcher($baseUrl, $apiKey);
$groupsResponse = $fetcher->fetchGroups($workspaceId);
// Process groups
foreach ($groupsResponse->getData() as $group) {
// Do something with each group
print_r($group->toArray());
}
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": [
{
"id": 7356,
"name": "Medusa Dragon",
"pages": []
},
{
"id": 7355,
"name": "Speedball",
"pages": []
},
{
"id": 7340,
"name": "testg",
"pages": [
9399
]
}
],
"meta": {
"workspaceId": 7068,
"pagination": {
"currentPage": 1,
"perPage": 100,
"totalItemsCount": 16,
"totalPagesCount": 1,
"nextPage": null,
"previousPage": null
}
}
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to retrieve groups for |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Query Parameters
Parameter | Type | Default | Description |
---|---|---|---|
page |
number |
1 |
Page number for pagination |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data[].id |
number |
Unique identifier of the group |
data[].name |
string |
Name of the group |
data[].pages |
number[] |
Array of page IDs that belong to the group |
meta.workspaceId |
number |
ID of the workspace the groups belong to |
meta.pagination.currentPage |
number |
Current page number |
meta.pagination.perPage |
number |
Number of items per page |
meta.pagination.totalItemsCount |
number |
Total number of groups available |
meta.pagination.totalPagesCount |
number |
Total number of pages |
meta.pagination.nextPage |
number? |
Next page number (null if there is no next page) |
meta.pagination.previousPage |
number? |
Previous page number (null if on first page) |
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully |
400 |
Bad request. Validation error — review input parameters |
401 |
Unauthorized. Authentication failed or missing credentials |
403 |
Forbidden. The user does not have the necessary permissions |
404 |
Not Found. The requested workspace could not be located |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled |
Create Group
Create a new group (folder) in a workspace.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/groups
curl -X POST "https://api.instapage.com/v1/workspaces/{workspaceId}/groups" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "New Group"}'
async function createGroup(workspaceId, name, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/groups`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ name })
});
if (response.statusCode !== 201) {
throw new Error(`Failed to create group: ${response.statusText}`);
}
return await response.json();
}
type GroupResponse = {
data: {
id: number;
name: string;
pages: number[];
};
meta: {
workspaceId: number;
};
};
async function createGroup(
workspaceId: number,
name: string,
apiKey: string
): Promise<GroupResponse> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/groups`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ name })
});
if (response.statusCode !== 201) {
throw new Error(`Failed to create group: ${response.statusText}`);
}
return await response.json();
}
<?php
declare(strict_types=1);
namespace InstapageGroupCreator;
readonly class Group
{
public function __construct(
public int $id,
public string $name,
public array $pages
) {}
public static function fromArray(array $data): self
{
return new self(
$data['id'],
$data['name'],
$data['pages'] ?? []
);
}
public function toArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'pages' => $this->pages
];
}
}
class GroupCreator
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function createGroup(int $workspaceId, string $name): Group
{
$url = sprintf(
'%s/v1/workspaces/%d/groups',
$this->baseUrl,
$workspaceId
);
$payload = json_encode(['name' => $name]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 201) {
throw new \RuntimeException("Failed to create group: HTTP $httpCode");
}
$responseData = json_decode($responseBody, true);
return Group::fromArray($responseData['data']);
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 7068;
$groupName = 'New Group';
$creator = new GroupCreator($baseUrl, $apiKey);
$newGroup = $creator->createGroup($workspaceId, $groupName);
echo "Group created with ID: " . $newGroup->id . " and name: " . $newGroup->name;
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
The above request returns JSON structured like this:
{
"data": {
"id": 7357,
"name": "New Group",
"pages": []
},
"meta": {
"workspaceId": 7068
}
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace to create the group in |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Request Body
Parameter | Type | Required | Description |
---|---|---|---|
name |
string |
Yes | The name of the new group |
Response JSON structure
JSON Path | Type | Description |
---|---|---|
data.id |
number |
Unique identifier of the created group |
data.name |
string |
Name of the group |
data.pages |
number[] |
Array of page IDs (empty for new groups) |
meta.workspaceId |
number |
ID of the workspace the group belongs to |
Response status codes
Status | Description |
---|---|
201 |
The request was processed successfully |
400 |
Bad request. Invalid name or other parameter |
401 |
Unauthorized. Authentication failed or missing credentials |
403 |
Forbidden. The user does not have the necessary permissions |
404 |
Not Found. The requested workspace could not be located |
409 |
Conflict. A group with the same name already exists |
413 |
Payload Too Large. Group name exceeds character limit |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled |
Update Group
Update an existing group (folder) in a workspace.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/groups/{groupId}
curl -X PUT "https://api.instapage.com/v1/workspaces/{workspaceId}/groups/{groupId}" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Updated Group Name"}'
async function updateGroup(workspaceId, groupId, name, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/groups/${groupId}`;
const response = await fetch(url, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ name })
});
if (!response.ok) {
throw new Error(`Failed to update group: ${response.statusText}`);
}
return response.status === 200;
}
async function updateGroup(
workspaceId: number,
groupId: number,
name: string,
apiKey: string
): Promise<boolean> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/groups/${groupId}`;
const response = await fetch(url, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ name })
});
if (!response.ok) {
throw new Error(`Failed to update group: ${response.statusText}`);
}
return response.status === 200;
}
<?php
declare(strict_types=1);
namespace InstapageGroupUpdater;
class GroupUpdater
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function updateGroup(int $workspaceId, int $groupId, string $name): bool
{
$url = sprintf(
'%s/v1/workspaces/%d/groups/%d',
$this->baseUrl,
$workspaceId,
$groupId
);
$payload = json_encode(['name' => $name]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to update group: HTTP $httpCode");
}
return true;
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 7068;
$groupId = 7357;
$newName = 'Updated Group Name';
$updater = new GroupUpdater($baseUrl, $apiKey);
$result = $updater->updateGroup($workspaceId, $groupId, $newName);
if ($result) {
echo "Group updated successfully.";
}
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace containing the group |
groupId |
number |
The ID of the group to update |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Request Body
Parameter | Type | Required | Description |
---|---|---|---|
name |
string |
Yes | New name for the group |
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully |
400 |
Bad request. Invalid name or other parameter |
401 |
Unauthorized. Authentication failed or missing credentials |
403 |
Forbidden. The user does not have the necessary permissions |
404 |
Not Found. The group or workspace could not be located |
409 |
Conflict. A group with the same name already exists |
413 |
Payload Too Large. Group name exceeds character limit |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled |
Delete Group
Delete a group (folder) from a workspace.
HTTP Request
https://api.instapage.com/v1/workspaces/{workspaceId}/groups/{groupId}
curl -X DELETE "https://api.instapage.com/v1/workspaces/{workspaceId}/groups/{groupId}" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json"
async function deleteGroup(workspaceId, groupId, apiKey) {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/groups/${groupId}`;
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Failed to delete group: ${response.statusText}`);
}
return response.status === 200;
}
async function deleteGroup(
workspaceId: number,
groupId: number,
apiKey: string
): Promise<boolean> {
const url = `https://api.instapage.com/v1/workspaces/${workspaceId}/groups/${groupId}`;
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Failed to delete group: ${response.statusText}`);
}
return response.status === 200;
}
<?php
declare(strict_types=1);
namespace InstapageGroupDeleter;
class GroupDeleter
{
public function __construct(
private string $baseUrl,
private string $apiKey
) {}
public function deleteGroup(int $workspaceId, int $groupId): bool
{
$url = sprintf(
'%s/v1/workspaces/%d/groups/%d',
$this->baseUrl,
$workspaceId,
$groupId
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: 'application/json'
]
]);
$responseBody = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new \RuntimeException('CURL Error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("Failed to delete group: HTTP $httpCode");
}
return true;
}
}
// Example usage
try {
$baseUrl = 'https://api.instapage.com';
$apiKey = 'your_api_key_here';
$workspaceId = 7068;
$groupId = 7357;
$deleter = new GroupDeleter($baseUrl, $apiKey);
$result = $deleter->deleteGroup($workspaceId, $groupId);
if ($result) {
echo "Group deleted successfully.";
}
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Path Parameters
Parameter | Type | Description |
---|---|---|
workspaceId |
number |
The ID of the workspace containing the group |
groupId |
number |
The ID of the group to delete |
Headers
Content-Type: application/json
Authorization: Bearer TOKEN
Response status codes
Status | Description |
---|---|
200 |
The request was processed successfully and the group was deleted |
400 |
Bad request. Group contains pages and cannot be deleted |
401 |
Unauthorized. Authentication failed or missing credentials |
403 |
Forbidden. The user does not have the necessary permissions |
404 |
Not Found. The group or workspace could not be located |
429 |
Too Many Requests. The server is rejecting requests due to excessive rate of requests. Please slow down and retry after some time |
500 |
Internal Server Error. An unexpected condition prevented the request from being fulfilled |
Related articles
Instapage API Examples
This document provides examples of how to interact with the Instapage API using different programming languages. Each example demonstrates how to fetch workspaces, pages, form submissions, and analytics data from Instapage.
Table of Contents
Node.js TypeScript Example
node -v # Should be v22.9.0
npm -v # Should be 10.8.3
node --experimental-strip-types example.ts # Replace example.ts with your file name
import fs from 'fs';
import { finished } from 'stream/promises';
import https from 'https';
class InstapageAPI {
constructor(token) {
this.token = token;
this.baseURL = 'https://api.instapage.com/v1';
}
getAllWorkspaces() {
return this.request('/workspaces');
}
request(endpoint, method, data) {
method = method || 'GET';
const url = this.baseURL + endpoint;
const options = {
method: method,
headers: {
'Authorization': 'Bearer ' + this.token,
'Content-Type': 'application/json'
}
};
return new Promise((resolve, reject) => {
const req = https.request(url, options, (res) => {
let responseBody = '';
res.on('data', (chunk) => {
responseBody += chunk;
});
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(JSON.parse(responseBody));
} else {
reject(new Error('HTTP Error: ' + res.statusCode + ', URL: ' + url + ', RESPONSE: ' + responseBody));
}
});
});
req.on('error', (error) => {
reject(new Error('Request error: ' + error.message));
});
if (method === 'POST' && data) {
req.write(JSON.stringify(data));
}
req.end();
});
}
getAllPages(workspaceId) {
return this.request('/workspaces/' + workspaceId + '/pages');
}
getFormSubmissions(workspaceId, pageIds) {
const self = this;
return new Promise((resolve, reject) => {
let results = [];
const maxOfRounds = Math.ceil(pageIds.length / 100);
let currentRound = 0;
function processRound() {
if (currentRound >= maxOfRounds) {
resolve(results);
return;
}
const selectedPageIds = pageIds.slice(currentRound * 100, (currentRound + 1) * 100);
const data = {
pages: selectedPageIds,
timeframe: {
start: Math.floor(Date.now() / 1000) - 30 * 24 * 60 * 60,
end: Math.floor(Date.now() / 1000)
}
};
self.request('/workspaces/' + workspaceId + '/submissions', 'POST', data)
.then(function(response) {
results = results.concat(response.data.submissions);
currentRound++;
processRound();
})
.catch(reject);
}
processRound();
});
}
getAnalytics(workspaceId, pageIds) {
const self = this;
return new Promise((resolve, reject) => {
let results = [];
const maxOfRounds = Math.ceil(pageIds.length / 100);
let currentRound = 0;
function processRound() {
if (currentRound >= maxOfRounds) {
resolve(results);
return;
}
const selectedPageIds = pageIds.slice(currentRound * 100, (currentRound + 1) * 100);
const data = {
pages: selectedPageIds,
interval: 'daily',
timeframe: {
start: Math.floor(Date.now() / 1000) - 30 * 24 * 60 * 60,
end: Math.floor(Date.now() / 1000)
},
grouping: ['pageId']
};
self.request('/workspaces/' + workspaceId + '/analytics', 'POST', data)
.then(function(response) {
results = results.concat(response.data);
currentRound++;
processRound();
})
.catch(reject);
}
processRound();
});
}
}
function createCsv(filename, data, headers) {
return new Promise((resolve, reject) => {
const csvContent = [
headers.join(','),
...data.map(row => row.map(String).join(','))
].join('\n');
fs.writeFile(filename, csvContent, function(err) {
if (err) {
reject(err);
} else {
console.log('CSV file "' + filename + '" created successfully.');
resolve();
}
});
});
}
function main() {
const token = ''; // Replace with your actual API token
const api = new InstapageAPI(token);
api.getAllWorkspaces()
.then(function(response) {
const workspaces = response.data;
console.log('Found ' + workspaces.length + ' workspaces');
const allLeads = [];
const allAnalytics = [];
function processWorkspace(index) {
if (index >= workspaces.length) {
return Promise.all([
createCsv('leads.csv', allLeads, ['Workspace ID', 'Workspace Name', 'Page ID', 'Submission ID', 'Created At', 'Fields']),
createCsv('analytics.csv', allAnalytics, ['Workspace ID', 'Workspace Name', 'Page ID', 'Date', 'Visits', 'Conversions', 'Leads'])
]);
}
const workspace = workspaces[index];
console.log('Processing workspace: ' + workspace.workspaceName + ' (ID: ' + workspace.workspaceId + ')');
return api.getAllPages(workspace.workspaceId)
.then(function(response) {
const pages = response.data;
console.log('Found ' + pages.length + ' pages in workspace ' + workspace.workspaceName);
const pageIds = pages.map(function(page) { return page.id; });
return Promise.all([
api.getFormSubmissions(workspace.workspaceId, pageIds),
api.getAnalytics(workspace.workspaceId, pageIds)
]);
})
.then(function([submissions, analytics]) {
submissions.forEach(function(submission) {
allLeads.push([
workspace.workspaceId,
workspace.workspaceName,
submission.pageId,
submission.id,
submission.createdAt,
JSON.stringify(submission.fields)
]);
});
analytics.forEach(function(analytic) {
allAnalytics.push([
workspace.workspaceId,
workspace.workspaceName,
analytic.key.pageId,
analytic.key.date,
analytic.visit,
analytic.conversion,
analytic.leads
]);
});
return processWorkspace(index + 1);
});
}
return processWorkspace(0);
})
.then(function() {
console.log('All data processed successfully.');
})
.catch(function(error) {
console.error('An error occurred:', error.message);
});
}
main();
Code Overview
This example uses TypeScript with Node.js version 22.9.0. It demonstrates how to:
- Authenticate with the Instapage API
- Fetch all workspaces
- For each workspace, fetch all pages
- Get form submissions for each page
- Get analytics data for each page
- Export the collected data to CSV files
Key Components
InstapageAPI
class: Handles all API interactionscreateCsv
function: Exports data to CSV formatmain
function: Orchestrates the entire data collection process
Endpoints Used
/workspaces
: GET request to fetch all workspaces/workspaces/{workspaceId}/pages
: GET request to fetch all pages in a workspace/workspaces/{workspaceId}/submissions
: POST request to fetch form submissions/workspaces/{workspaceId}/analytics
: POST request to fetch analytics data
Results
The script generates two CSV files:
1. leads.csv
: Contains form submission data
2. analytics.csv
: Contains analytics data for each page
Node.js JavaScript Example
node -v # Should be v22.9.0
npm -v # Should be 10.8.3
node example.js # Replace example.js with your file name
const fs = require('fs');
const https = require('https');
class InstapageAPI {
constructor(token) {
this.token = token;
this.baseURL = 'https://api.instapage.com/v1';
}
getAllWorkspaces() {
return this.request('/workspaces');
}
request(endpoint, method, data) {
method = method || 'GET';
const url = this.baseURL + endpoint;
const options = {
method: method,
headers: {
'Authorization': 'Bearer ' + this.token,
'Content-Type': 'application/json'
}
};
return new Promise((resolve, reject) => {
const req = https.request(url, options, (res) => {
let responseBody = '';
res.on('data', (chunk) => {
responseBody += chunk;
});
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(JSON.parse(responseBody));
} else {
reject(new Error('HTTP Error: ' + res.statusCode + ', URL: ' + url + ', RESPONSE: ' + responseBody));
}
});
});
req.on('error', (error) => {
reject(new Error('Request error: ' + error.message));
});
if (method === 'POST' && data) {
req.write(JSON.stringify(data));
}
req.end();
});
}
getAllPages(workspaceId) {
return this.request('/workspaces/' + workspaceId + '/pages');
}
getFormSubmissions(workspaceId, pageIds) {
const self = this;
return new Promise((resolve, reject) => {
let results = [];
const maxOfRounds = Math.ceil(pageIds.length / 100);
let currentRound = 0;
function processRound() {
if (currentRound >= maxOfRounds) {
resolve(results);
return;
}
const selectedPageIds = pageIds.slice(currentRound * 100, (currentRound + 1) * 100);
const data = {
pages: selectedPageIds,
timeframe: {
start: Math.floor(Date.now() / 1000) - 30 * 24 * 60 * 60,
end: Math.floor(Date.now() / 1000)
}
};
self.request('/workspaces/' + workspaceId + '/submissions', 'POST', data)
.then(function(response) {
results = results.concat(response.data.submissions);
currentRound++;
processRound();
})
.catch(reject);
}
processRound();
});
}
getAnalytics(workspaceId, pageIds) {
const self = this;
return new Promise((resolve, reject) => {
let results = [];
const maxOfRounds = Math.ceil(pageIds.length / 100);
let currentRound = 0;
function processRound() {
if (currentRound >= maxOfRounds) {
resolve(results);
return;
}
const selectedPageIds = pageIds.slice(currentRound * 100, (currentRound + 1) * 100);
const data = {
pages: selectedPageIds,
interval: 'daily',
timeframe: {
start: Math.floor(Date.now() / 1000) - 30 * 24 * 60 * 60,
end: Math.floor(Date.now() / 1000)
},
grouping: ['pageId']
};
self.request('/workspaces/' + workspaceId + '/analytics', 'POST', data)
.then(function(response) {
results = results.concat(response.data);
currentRound++;
processRound();
})
.catch(reject);
}
processRound();
});
}
}
function createCsv(filename, data, headers) {
return new Promise((resolve, reject) => {
const csvContent = [
headers.join(','),
...data.map(row => row.map(String).join(','))
].join('\n');
fs.writeFile(filename, csvContent, function(err) {
if (err) {
reject(err);
} else {
console.log('CSV file "' + filename + '" created successfully.');
resolve();
}
});
});
}
function main() {
const token = ''; // Replace with your actual API token
const api = new InstapageAPI(token);
api.getAllWorkspaces()
.then(function(response) {
const workspaces = response.data;
console.log('Found ' + workspaces.length + ' workspaces');
const allLeads = [];
const allAnalytics = [];
function processWorkspace(index) {
if (index >= workspaces.length) {
return Promise.all([
createCsv('leads.csv', allLeads, ['Workspace ID', 'Workspace Name', 'Page ID', 'Submission ID', 'Created At', 'Fields']),
createCsv('analytics.csv', allAnalytics, ['Workspace ID', 'Workspace Name', 'Page ID', 'Date', 'Visits', 'Conversions', 'Leads'])
]);
}
const workspace = workspaces[index];
console.log('Processing workspace: ' + workspace.workspaceName + ' (ID: ' + workspace.workspaceId + ')');
return api.getAllPages(workspace.workspaceId)
.then(function(response) {
const pages = response.data;
console.log('Found ' + pages.length + ' pages in workspace ' + workspace.workspaceName);
const pageIds = pages.map(function(page) { return page.id; });
return Promise.all([
api.getFormSubmissions(workspace.workspaceId, pageIds),
api.getAnalytics(workspace.workspaceId, pageIds)
]);
})
.then(function(results) {
const submissions = results[0];
const analytics = results[1];
submissions.forEach(function(submission) {
allLeads.push([
workspace.workspaceId,
workspace.workspaceName,
submission.pageId,
submission.id,
submission.createdAt,
JSON.stringify(submission.fields)
]);
});
analytics.forEach(function(analytic) {
allAnalytics.push([
workspace.workspaceId,
workspace.workspaceName,
analytic.key.pageId,
analytic.key.date,
analytic.visit,
analytic.conversion,
analytic.leads
]);
});
return processWorkspace(index + 1);
});
}
return processWorkspace(0);
})
.then(function() {
console.log('All data processed successfully.');
})
.catch(function(error) {
console.error('An error occurred:', error.message);
});
}
main();
This example is similar to the TypeScript version but uses plain JavaScript. The functionality and endpoints used are the same.
PHP Example
php -v # Should be PHP 7.4.33 (cli)
php example.php # Replace example.php with your file name
<?php
class InstapageAPI
{
private $token;
private $baseURL = 'https://api.instapage.com/v1';
public function __construct($token)
{
$this->token = $token;
}
public function getAllWorkspaces()
{
$response = $this->request('/workspaces');
return $response['data'];
}
private function request($endpoint, $method = 'GET', $data = null)
{
$url = $this->baseURL . $endpoint;
$headers = [
'Authorization: Bearer ' . $this->token,
'Content-Type: application/json'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
}
$response = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception('Curl error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 200 && $httpCode < 300) {
return json_decode($response, true);
} else {
throw new Exception("HTTP Error: $httpCode, URL: $url, RESPONSE: $response");
}
}
public function getAllPages($workspaceId)
{
$response = $this->request("/workspaces/$workspaceId/pages");
return $response['data'];
}
public function getFormSubmissions($workspaceId, $pageIds)
{
$results = [];
$currentRound = 0;
$maxOfRounds = ceil(count($pageIds) / 100);
while ($currentRound < $maxOfRounds) {
$selectedPageIds = array_slice($pageIds, $currentRound * 100, 100);
$data = [
'pages' => $selectedPageIds,
'timeframe' => [
'start' => strtotime('-30 days'),
'end' => time()
]
];
$response = $this->request("/workspaces/$workspaceId/submissions", 'POST', $data);
$results = [...$results, ...$response['data']['submissions']];
$currentRound += 1;
}
return $results;
}
public function getAnalytics($workspaceId, $pageIds)
{
$results = [];
$currentRound = 0;
$maxOfRounds = ceil(count($pageIds) / 100);
while ($currentRound < $maxOfRounds) {
$selectedPageIds = array_slice($pageIds, $currentRound * 100, 100);
$data = [
'pages' => $selectedPageIds,
'interval' => 'daily',
'timeframe' => [
'start' => strtotime('-30 days'),
'end' => time()
],
'grouping' => ['pageId']
];
$response = $this->request("/workspaces/$workspaceId/analytics", 'POST', $data);
$results = [...$results, ...$response['data']];
$currentRound += 1;
}
return $results;
}
}
function createCsv($filename, $data, $headers)
{
$fp = fopen($filename, 'w');
fputcsv($fp, $headers);
foreach ($data as $row) {
fputcsv($fp, $row);
}
fclose($fp);
echo "CSV file '$filename' created successfully.\n";
}
function main()
{
$token = ''; // Replace with your actual API token
$api = new InstapageAPI($token);
try {
$workspaces = $api->getAllWorkspaces();
echo "Found " . count($workspaces) . " workspaces\n";
$allLeads = [];
$allAnalytics = [];
foreach ($workspaces as $workspace) {
echo "Processing workspace: {$workspace['workspaceName']} (ID: {$workspace['workspaceId']})\n";
$pages = $api->getAllPages($workspace['workspaceId']);
echo "Found " . count($pages) . " pages in workspace {$workspace['workspaceName']}\n";
$pageIds = array_column($pages, 'id');
// Fetch and process leads
$submissions = $api->getFormSubmissions($workspace['workspaceId'], $pageIds);
foreach ($submissions as $submission) {
$allLeads[] = [
$workspace['workspaceId'],
$workspace['workspaceName'],
$submission['pageId'],
$submission['id'],
$submission['createdAt'],
json_encode($submission['fields'])
];
}
// Fetch and process analytics
$analytics = $api->getAnalytics($workspace['workspaceId'], $pageIds);
foreach ($analytics as $analytic) {
$allAnalytics[] = [
$workspace['workspaceId'],
$workspace['workspaceName'],
$analytic['key']['pageId'],
$analytic['key']['date'],
$analytic['visit'],
$analytic['conversion'],
$analytic['leads']
];
}
}
// Create CSV for leads
createCsv('leads.csv', $allLeads, ['Workspace ID', 'Workspace Name', 'Page ID', 'Submission ID', 'Created At', 'Fields']);
// Create CSV for analytics
createCsv('analytics.csv', $allAnalytics, ['Workspace ID', 'Workspace Name', 'Page ID', 'Date', 'Visits', 'Conversions', 'Leads']);
} catch (Exception $e) {
echo "An error occurred: " . $e->getMessage() . "\n";
}
}
main();
Code Overview
This example uses PHP 7.4.33 and demonstrates the same functionality as the Node.js examples.
Key Differences
- Uses cURL for HTTP requests instead of Node's built-in https module
- PHP-specific syntax and conventions
Conclusion
These examples demonstrate how to interact with the Instapage API to collect workspace, page, form submission, and analytics data. The process is similar across all three implementations (TypeScript, JavaScript, and PHP), with the main differences being in language-specific syntax and HTTP request handling.
Remember to replace the empty token string with your actual Instapage API token before running any of these scripts. Also, ensure you have the necessary permissions to access the data you're requesting through the API.