Customize Core Pages

This article describes how to customize the core pages of API Portal.
apip50
This article describes how to customize the core pages of API Portal.
2
2
What You Can Customize
You can fully customize the following core API Portal pages to provide your customers with a fully branded experience of the public page:
  • Home
  • Login
  • Sign Up
  • Account Setup
  • Reset Password
  • New Password
You can bundle your custom pages (and all the related files, for example, js and css) in a zip file. Upload this file to API Portal and apply the customization, instantly.
The
Content Management
menu provides an easy way to set your custom pages as the default. Your current home page is automatically listed as "default".
You can either use the templates provided in the Content Management page or use your own html content to apply the customization.
Use Templates for Customization
API Portal provides a set of templates for each of the core API Portal pages that you want to customize. Each template file contains the minimum content that is required to make the corresponding page work as expected. You can create your own custom pages by customizing the template files or by creating your own files from scratch. The templates are available in
SampleTemplates.zip
file that you have to download from
Content Management, Upload Page Bundles
section.
The zip file contains six html pages and folders containing corresponding js and css files. This zip also contains a common folder where you can put common resources like js and css files, which can be applied across all pages.
Templates ensure easier and faster customization.
The template file works similar to the default API Portal page that you want to customize. Ensure that you understand the functionality before attempting to change the files. Random changes in the code might result in an unstable page.
Prerequisites for Customization
Verify the following prerequisites before customizing the core pages:
  • You have Tenant or Portal Administrator access in API Portal.
  • You are aware of the external authentication schemes that must be applied on the Login page.
  • You know that the permissible size limit for the zip file should not exceed 15 MB.
  • The following file types are supported:
    • png
    • jpg
    • jpeg
    • gif
    • ico
    • svg
    • html
    • css
    • js
    • ttf
    • woff
    • woff2
    • otf
  • File names (including the zip file) should only contain alphanumeric characters, underscores, spaces, and hyphens.
  • You have experience in coding and consuming the APIs. Read the APIs that are applicable for the page you want to customize. The following table lists the minimum APIs that you can consume to make the pages work as expected:
    Page
    APIs
    Description
    Login
    /api/{tenantId}/authenticate/login
    To authenticate users using API Portal, call the POST method on this API with payload containing user credentials.
    /admin/public/auth/schemes
    Provides a list of authentication schemes available for the tenant. These authentication schemes are displayed in the Login page.
    "/api/{tenantId}/authenticate/getPublicKey
    'If the API returns the public key, then the password has to be encrypted in the "/api/{tenantId}/authenticate/login" payload.'
    Sign Up
    /admin/Portal.svc/Registrations
    To place a sign-up request, call POST method on this API with payload containing user information.
    Account Setup
    /admin/accountSetup
    Account Setup page is loaded with a token as a query parameter, which is required for setting up the account. To validate the token, call GET method on this API with token as query parameter.
    /api/{tenantId}/authenticate/getPublicKey
    If the API returns the public key, then the password has to be encrypted in the "/admin/accountSetup" payload.
    /admin/accountSetup
    To complete the account setup process, call PUT method on this API with payload containing user information, password, and token.
    Reset Password
    /admin/Portal.svc/ResetMyPassword()
    To place a request to update the password, call GET method on this API with username as query parameter.
    New Password
    /admin/passwordResetTokenValidate
    This page is loaded with a token as path parameter, which is required in the password reset process. The token can be validated by calling GET method on this API with token as query parameter.
    /api/{tenantId}/authenticate/getPublicKey
    If the API returns the public key, then encrypt the password in the "/admin/UpdateMyPassword" payload.
    /admin/UpdateMyPassword
    To complete the reset password process, call POST method on this API with payload containing password and token.
APIs to Create Custom Pages
Ensure you are aware of the APIs required to make the custom pages work, as expected.
For example, to customize the Login page, you need text boxes for entering the username and password, display the authorization schemes (portal, LDAP, SAML, and so on), and a
Login
button. The user must select an authorization scheme, and then enter the credentials. When the user clicks
Login
, API Portal calls an API to validate the user credentials.
The following Swagger representation is created from a static JSON file.
{ "swagger": "2.0", "info": { "version": "1.0.0", "title": "CA Customize Portal Pages" }, "host": "apim.dev.ca.com", "basePath": "/", "tags": [ { "name": "Login", "description": "" }, { "name": "Reset Password", "description": "" }, { "name": "Sign Up", "description": "" }, { "name": "Home", "description": "" }, { "name": "Account Setup", "description": "" }, { "name": "New Password", "description": "" }, { "name": "Common APIs", "description": "" } ], "schemes": [ "https" ], "paths": { "/admin/cmsSettings": { "get": { "tags": [ "Common APIs" ], "summary": "Fetch CMS Settings", "description": "Use 'REGISTRATION_STATUS' field value to check if the SignUp functionality is enabled or not.", "operationId": "getCMSSettings", "produces": [ "application/json" ], "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/CMSSettings" } } } } }, "/api/{tenantId}/branding/1.0/themes": { "get": { "tags": [ "Common APIs" ], "summary": "Fetch Theme Settings", "description": "Returns the settings for the applied theme on the tenant.", "operationId": "getTheme", "produces": [ "application/json" ], "parameters": [ { "$ref": "#/parameters/tenantParam" } ], "responses": { "200": { "description": "Theme related settings.", "schema": { "$ref": "#/definitions/ThemesSettings" } } } } }, "/admin/public/auth/schemes": { "get": { "tags": [ "Login" ], "summary": "Fetch the available Authentication Schemes", "description": "Fetch the available Authentication Schemes along with Public Key which would be used for encrypting login password if Enhanced Security is enabled for default APIM auth scheme or LDAP auth schemes.", "operationId": "getAuthSchemes", "produces": [ "application/json" ], "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/AuthSchemes" } } } } }, "/api/{tenantId}/authenticate/login": { "post": { "tags": [ "Login" ], "summary": "Login API", "description": "Used for authenticating the user.<br>When Enhanced Security is enabled /admin/public/auth/schemes will return publicKey which should be used to encrypt the password and passed as header.", "operationId": "submitLoginForm", "consumes": [ "application/json" ], "produces": [ "application/json" ], "parameters": [ { "$ref": "#/parameters/publicKeyHeader" }, { "$ref": "#/parameters/tenantParam" }, { "$ref": "#/parameters/LoginParam" } ], "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/LoginResponse" } }, "400": { "description": "Bad Request" }, "401": { "description": "Unauthorized" }, "500": { "description": "Internal Server Error" } } } }, "/admin/Portal.svc/Registrations": { "post": { "tags": [ "Sign Up" ], "summary": "Submit registration request", "description": "Used to signup a new user.", "operationId": "submitSignUpForm", "consumes": [ "application/json" ], "produces": [ "application/json" ], "parameters": [ { "$ref": "#/parameters/SignUpParam" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/SignUpResponse" } }, "400": { "description": "Bad Request" }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/Error" } } } } }, "/admin/navigation": { "get": { "tags": [ "Home" ], "summary": "Fetch the navigation list", "description": "", "produces": [ "application/json" ], "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/Navigation" } } } } }, "/admin/public/auth/schemes/passwordPolicies": { "get": { "tags": [ "Common APIs" ], "summary": "Fetch password policies for the tenant", "description": "Fetch password policy when Activating user or Resetting user password, a set of rules user password must adhere.", "produces": [ "application/json" ], "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/PasswordPolicies" } } } } }, "/api/{tenantId}/authenticate/getPublicKey": { "get": { "summary": "Fetch public key for password encryption", "description": "Fetch public key which would be used for encrypting user password when Activating User or Resetting Password if Enhanced Security is enabled.", "produces": [ "application/json" ], "tags": [ "Common APIs" ], "parameters": [ { "$ref": "#/parameters/tenantParam" } ], "responses": { "200": { "description": "Success", "schema": { "type": "object", "properties": { "respCode": { "type": "integer" }, "respMsg": { "type": "string" }, "publicKey": { "type": "string" } }, "example": { "respCode": 200, "respMsg": "Successfully fetched public key", "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAocaSLKk9v2BVYEDDN2jXmFn9ygnjeUYIs+aFNF8KLsI+l9cE3TcLWo" } } } } } }, "/admin/UpdateMyPassword": { "post": { "summary": "Reset the password of an existing user", "produces": [ "application/json" ], "tags": [ "New Password" ], "description": "API to reset password.<br>When Enhanced Security is enabled /api/{tenantId}/authenticate/getPublicKey will return publicKey which should be used to encrypt the password and passed as header.", "parameters": [ { "$ref": "#/parameters/publicKeyHeader" }, { "in": "body", "name": "password", "description": "The fields required to reset password.", "schema": { "type": "object", "required": [ "passwordDetails" ], "properties": { "password": { "type": "string" }, "token": { "type": "string" }, "Uuid": { "type": "string" } }, "example": { "password": "[email protected]", "token": "MDVhMGM0ZDItNmQwNS00YWNjLTk0OGUtNmZkZWIwMzhjMTlh", "Uuid": "{{GENERATED_GUID}}" } } } ], "responses": { "200": { "description": "Successful update" }, "400": { "description": "Bad Request" }, "500": { "description": "Internal Server Error" } } } }, "/admin/accountSetup": { "put": { "summary": "Activate user account", "produces": [ "application/json" ], "tags": [ "Account Setup" ], "description": "API to complete account setup.<br>When Enhanced Security is enabled /api/{tenantId}/authenticate/getPublicKey will return publicKey which should be used to encrypt the password and passed as header.", "parameters": [ { "$ref": "#/parameters/publicKeyHeader" }, { "in": "query", "name": "authenticity-token", "type": "string" }, { "in": "body", "name": "AccountSetup", "schema": { "type": "object", "properties": { "token": { "type": "string" }, "uuid": { "type": "string" }, "firstName": { "type": "string" }, "lastName": { "type": "string" }, "email": { "type": "string" }, "userName": { "type": "string" }, "password": { "type": "string" } }, "example": { "token": "MDVhMGM0ZDItNmQwNS00YWNjLTk0OGUtNmZkZWIwMzhjMTlh", "Uuid": "{{GENERATED_GUID}}", "firstName": "First", "lastName": "Last", "email": "[email protected]", "userName": "admin", "password": "[email protected]" } } } ], "responses": { "200": { "description": "Success" }, "400": { "description": "Bad Request" }, "500": { "description": "Internal Server Error" } } }, "get": { "summary": "Validate activation token", "description": "For checking if activation token is valid or not.", "produces": [ "application/json" ], "tags": [ "Account Setup" ], "parameters": [ { "in": "query", "name": "token", "type": "string" } ], "responses": { "200": { "description": "Success" } } } }, "/admin/Portal.svc/ResetMyPassword()": { "get": { "summary": "Initiate password reset for a user", "description": "On submitting username an email is sent to user for resetting the password.", "produces": [ "application/json" ], "tags": [ "Reset Password" ], "parameters": [ { "in": "query", "name": "Username", "type": "string" } ], "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/ResultResponse" } } } } }, "/admin/passwordResetTokenValidate": { "get": { "summary": "Validate password reset token", "description": "For checking if password reset token is valid or not.", "produces": [ "boolean" ], "tags": [ "New Password" ], "parameters": [ { "in": "query", "name": "token", "type": "string" } ], "responses": { "200": { "description": "Success", "schema": { "type": "boolean", "example": true } } } } }, "/admin/Portal.svc/UserNameUnique()": { "get": { "summary": "Username unique check", "description": "For validating if username is unique or not.", "produces": [ "application/json" ], "tags": [ "Account Setup" ], "parameters": [ { "in": "query", "name": "Name", "type": "string", "description": "Apply encodeURIComponent on name before sending" } ], "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/ResultResponse" } } } } }, "/admin/sessionCheck": { "get": { "summary": "User session check", "description": "For validating if user is loggedIn or not.", "produces": [ "application/json" ], "tags": [ "Common APIs" ], "responses": { "200": { "description": "Success", "schema": { "type": "object", "properties": { "status": { "type": "boolean" } }, "example": { "status": true } } } } } }, "/admin/Portal.svc/OrganizationNameUnique()": { "get": { "summary": "Username unique check", "description": "For validating if username is unique or not.", "produces": [ "application/json" ], "tags": [ "Reset Password" ], "parameters": [ { "in": "query", "name": "Name", "type": "string", "description": "Apply encodeURIComponent on name before sending" } ], "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/ResultResponse" } } } } } }, "parameters": { "publicKeyHeader": { "name": "publicKey", "in": "header", "description": "an encryption key", "required": false, "type": "string" }, "tenantParam": { "name": "tenantId", "in": "path", "description": "ID of tenant", "required": true, "type": "string", "x-example": "apim" }, "LoginParam": { "name": "body", "in": "body", "description": "Login parameters", "required": true, "schema": { "$ref": "#/definitions/LoginRequest" } }, "SignUpParam": { "name": "body", "in": "body", "description": "SignUp parameters", "required": true, "schema": { "$ref": "#/definitions/SignUpRequest" } } }, "definitions": { "BaseResponse": { "type": "object", "properties": { "respCode": { "type": "string" }, "respMsg": { "type": "string" } } }, "BaseResponseInteger": { "type": "object", "properties": { "respCode": { "type": "integer" }, "respMsg": { "type": "string" } } }, "CMSSettings": { "description": "A representation of CMS Settings", "type": "object", "properties": { "REGISTRATION_STATUS": { "type": "string" }, "PORTAL_NAME": { "type": "string" }, "REGISTRATION_REQUEST_WORKFLOW": { "type": "string" }, "REGISTRATION_TERMS_OF_USE": { "type": "string" }, "ADMIN_EMAIL": { "type": "string" }, "SSO_ENABLED": { "type": "string" }, "ACTIVATE_MSSO": { "type": "string" } }, "example": { "REGISTRATION_STATUS": "ENABLED", "PORTAL_NAME": "CA Technologies Developer Network", "REGISTRATION_REQUEST_WORKFLOW": "ENABLED", "REGISTRATION_TERMS_OF_USE": "By clicking \"I Accept the Terms and Conditions\" you, on behalf of your employer or contracted entity, agree that your use and access to the CA API Management SaaS Portal Application Programmable Interface (\"PAPI\") will be subject to and governed by this CA API Policy (the \"Policy\"). You must be authorized to use the CA API Management SaaS Portal by CA or an authorized CA Partner. If you do not, or cannot agree to the Policy, you must not use or access the PAPI. Your continued use of the PAPI constitutes acceptance of any changes to the Policy. Under the Policy, \"CA\", \"we\" or \"us\" means CA Inc., with offices located at 520 Madison Avenue, New York, NY 10022, and its subsidiaries and affiliates. \\n\\nI. CA makes the PAPI available to provide programmatic access to CA's API Management SaaS Solution. CA reserves the right to discontinue, change, or version the PAPI at any time, in its sole discretion, and makes no guarantees or warranties that the software, scripts or programmatic routines will continue to operate following any changes. CA shall have no liability to you or any third party any downtime, changes or withdrawal of the PAPI. Where possible, we will take commercially reasonable efforts to provide you advanced notice of any changes. CA retains all rights in and to its intellectual property, including but not limited to, the PAPI, software, tools, data materials, information and derivatives or modifications thereof. CA reserves all rights not expressly granted in this Policy. \\n\\nII. In order to access the PAPI you may be required to provide certain information, you agree that all information is current and accurate. You agree to inform CA of any changes. You may only access and use the PAPI in accordance with the technical documentation supplied by CA. CA may set limits and restrictions around acceptable use of the PAPI. You agree that you will not attempt to disable or circumvent these limitations. \\n\\nIII. You agree that you will not: \\na) Sublicense the PAPI to any third party. You further agree that you will not create an API that functions in a substantially similar way to the PAPI and offer it for use to third parties. \\nb) Perform or take any actions that will introduce any viruses, worms, defects, Trojan horses, malware or have the effect of disabling, interfering, disrupting or impairing the CA product or services. \\nc) Except where prohibited by law, reverse engineer or decompile any source code through the PAPI or any related CA product or service. \\nd) Use the PAPI to process or store any sensitive, personal or confidential information. \\ne) Use the PAPI, directly or indirectly, to benchmark or create a product or service that is substantially similar to the CA API Management SaaS Portal. \\nf) Remove, alter or obscure any CA marks. \\ng) Do the following with the PAPI content: \\na. Change, alter or misrepresent directly or indirectly the source or ownership in any way \\nb. Copy, translate, modify, create derivative works, publicly display or sublicense to any third party. \\nc. Perform any mechanism to keep permanent copies of content or keep content longer than permitted in the cache header. \\n\\nIV. EXCEPT AS EXPRESSLY STATED HEREIN, CA DOES NOT MAKE ANY REPRESENTATIONS OR WARRANTIES ABOUT THE PAPI. SPECIFICALLY, ITS FUNCTIONALITY, RELIABILITY, AVAILABILITY OR ABILITY TO MEET YOUR SPECIFIC NEEDS OR REQUIREMENTS. THE PAPI IS PROVIDED ON AN \"AS-IS\" BASIS. EXCEPT WHERE PROHIBITED BY LAW, CA DISCLAIMS THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. CA, ITS SUPPLIERS, DISTRIBUTORS AND LICENSORS, WILL NOT BE RESPONSIBLE FOR LOST PROFITS, REVENUES OR DATA; OR INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF ADVISED IN ADVANCE OF THE POSSIBLE OF SUCH DAMAGES. TO THE EXTENT PERMITTED BY LAW, THE TOTAL LIABILITY OF CA, ITS SUPPLIERS AND DISTRIBUTORS, FOR ANY CLAIM ARISING FROM OR RELATED TO THE POLICY IS LIMITED TO 100.00 USD. \\n\\nV. You may discontinue using the PAPI at any time. In the event of termination or expiration by you or CA, Sections III, IV and VI will survive. \\n\\nVI. The governing law and venue for any disputes or claims arising out of or related to the PAPI will be governed by the terms of your agreement with CA for use of the CA API Management SaaS Portal.", "ADMIN_EMAIL": "[email protected]", "SSO_ENABLED": "false", "ACTIVATE_MSSO": "false" } }, "AuthSchemes": { "allOf": [ { "$ref": "#/definitions/BaseResponseInteger" } ], "type": "object", "properties": { "authSchemes": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" }, "authMethod": { "type": "string" }, "editable": { "type": "boolean" }, "showFyp": { "type": "boolean" }, "credsReqd": { "type": "boolean" }, "defaultConfig": { "type": "boolean" }, "url": { "type": "string" }, "advancedConfigurations": { "type": "object", "properties": { "enhancedPasswordSecurity": { "type": "string" } } } } } }, "publicKey": { "type": "string" } }, "example": { "respCode": 200, "respMsg": "Successfully fetched Authentication Schemes", "authSchemes": [ { "uuid": "479c0a44-7f9d-42cf-b778-fbdb2e04e1a9", "name": "CA Technologies Developer Network", "description": "", "authMethod": "DEFAULT", "editable": true, "showFyp": true, "credsReqd": true, "defaultConfig": true, "url": "http://apim.dev.ca.com/admin/login", "advancedConfigurations": { "enhancedPasswordSecurity": "no" } } ], "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz5OfFKwJaCSjfPDP9DfSp4+4t9MkWqngRbUsviRFcBH9Ko6SNGNWzZlOeASZnukdxShnCueR6UcMvKwx9dlUXL6nNalR9k7OE4IYAwi4xXpligsGc4LWW+3AEkR9v4KaId1zD5Dhhcbw7BohUztHmV0zpGk0dzmstRR2sxMhjinXUpiK0xK3YGsOtBWgVxc9NHJwYJ0flHLWytp5SbJ6Kzx2LaJF2AZrGpQyMBhSV5TUJ45Dxw/UUUZvdBjrcwzWgq8QR5vmX5QjFfK+XN+O2K3oGmnyqxZ9anl87UxKu9AeD+i1ekWZrsH+khozBRhiUbNpHp8jO6CwpGRYNuSuAwIDAQAB" } }, "LoginResponse": { "allOf": [ { "$ref": "#/definitions/BaseResponse" } ], "type": "object", "properties": { "provider": { "type": "string" }, "referrer": { "type": "string" }, "dashboardPath": { "type": "string" } }, "example": { "respCode": "200", "respMsg": "Successfully authenticated user", "provider": "", "referrer": "", "dashboardPath": "" } }, "LoginRequest": { "type": "object", "properties": { "username": { "type": "string" }, "password": { "type": "string" }, "uuid": { "type": "string" }, "eula": { "type": "string" } }, "example": { "username": "admin", "password": "7layereyal7", "eula": "accept", "uuid": "{{GENERATED_GUID}}" } }, "ThemeBasic": { "description": "A representation of a Theme.", "type": "object", "properties": { "logo": { "type": "string", "description": "Base64 string of portal logo.", "maxLength": 716800 }, "favicon": { "type": "string", "description": "Base64 string of portal favicon.", "maxLength": 716800 }, "siteTitle": { "type": "string" }, "color": { "type": "object", "properties": { "siteTitle": { "type": "string" }, "pageTitle": { "type": "string" }, "background": { "type": "string" }, "bodyText": { "type": "string" }, "link": { "type": "string" }, "linkHover": { "type": "string" }, "smallText": { "type": "string" }, "borderColor": { "type": "string" }, "primaryButtonBackground": { "type": "string" }, "primaryButtonText": { "type": "string" }, "primaryButtonHover": { "type": "string" }, "headerBackground": { "type": "string" }, "headerLink": { "type": "string" }, "footerBackground": { "type": "string" }, "footerText": { "type": "string" }, "footerLink": { "type": "string" } } }, "typography": { "type": "object", "properties": { "siteTitle": { "type": "string" }, "pageTitle": { "type": "string" }, "bodyText": { "type": "string" }, "smallText": { "type": "string" }, "footerText": { "type": "string" }, "buttonText": { "type": "string" } } }, "fontSize": { "type": "object", "properties": { "siteTitle": { "type": "string" }, "pageTitle": { "type": "string" }, "bodyText": { "type": "string" }, "smallText": { "type": "string" }, "footerText": { "type": "string" }, "buttonText": { "type": "string" } } }, "display": { "type": "object", "properties": { "versionNumber": { "type": "boolean" }, "copyright": { "type": "boolean" } } }, "label": { "type": "object", "description": "Custom menu label.", "properties": { "service.publish.nav.manageapi.title": { "type": "string" }, "service.publish.nav.apps.title": { "type": "string" }, "service.publish.nav.apicatalog.title": { "type": "string" }, "service.publish.nav.apiexplorer.title": { "type": "string" } } } } }, "ThemeFontGetDto": { "type": "object", "properties": { "name": { "type": "string" }, "ttfUri": { "type": "string" }, "woffUri": { "type": "string" }, "woff2Uri": { "type": "string" }, "eotUri": { "type": "string" }, "otfUri": { "type": "string" } } }, "ThemesSettings": { "allOf": [ { "$ref": "#/definitions/ThemeBasic" } ], "type": "object", "properties": { "typography": { "type": "object", "properties": { "custom": { "type": "array", "items": { "$ref": "#/definitions/ThemeFontGetDto" } } } }, "images": { "type": "object", "properties": { "backgroundFooterUri": { "type": "string", "description": "Uri to background footer image" }, "backgroundHeaderUri": { "type": "string", "description": "Uri to background header image" } } } }, "example": { "logo": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAAA8CAYAAADFXvyQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/dpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjkxNkRBMDU0MEIzOERGMTE4N0Y3RTdFRUFERUI2NUM0IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjkwRkI0NDgwRTJCRjExRTNCRjE1QTU2MzE5RTY4QTIzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjkwRkI0NDdGRTJCRjExRTNCRjE1QTU2MzE5RTY4QTIzIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIElsbHVzdHJhdG9yIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OGNkYTBiNTMtYjNjZC00YTcyLWIyY2ItZjA5ZjliYzRlOGExIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjhj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", "favicon": "data:image/vnd.microsoft.icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////+/v7//T09P/39/f///////7+/v/39/f/9fX1//39/f///////Pz8//z8/P/+/v7////////////5+fn/urq6/2tra/9NTU3/WFhY/6Kiov+goKD/V1dX/05OTv+Ghob/u7u7/3Fxcf9wcHD/wcHB/9PT0//8/Pz/l5eX/xUVFf8AAAD/AAAA/wsLC/9BQUH/Dg4O/wEBAf8cHBz/Hh4e/yEhIf8EBAT/EBAQ/7Ozs//g4OD/y8vL/yQkJP8AAAD/Hx8f/4aGhv+VlZX/Pj4+/wAAAP9AQED/1dXV/8bGxv8zMzP/AAAA/xEREf/ExMT//////4eHh/8FBQX/AAAA/3l5ef//////+fn5/15eXv8AAAD/QkJC/+Hh4f//////hoaG/wAAAP8RERH/xMTE//////9nZ2f/AAAA/wQEBP+cnJz///////////+9vb3/Kioq/wQEBP82Njb/e3t7/1ZWVv8AAAD/ERER/8TExP//////cXFx/wAAAP8EBAT/m5ub////////////+Pj4/8bGxv99fX3/UFBQ/zk5Of8eHh7/AAAA/xEREf/Dw8P//////6Kiov8MDAz/AAAA/21tbf/6+vr/8/Pz/39/f/9MTEz/hoaG/+np6f/t7e3/cXFx/wAAAP8RERH/xcXF///////n5+f/R0dH/wAAAP8TExP/ZWVl/2BgYP8NDQ3/BQUF/0VFRf9jY2P/b29v/x8fH/8AAAD/IyMj/9ra2v///////////83Nzf9HR0f/CwsL/wAAAP8AAAD/ERER/1tbW/9DQ0P/AgIC/wAAAP8DAwP/GBgY/4yMjP/7+/v/////////////////6urq/7Kysv+SkpL/lZWV/76+vv/w8PD/zc3N/56env+Pj4//mZmZ/8fHx//4+Pj/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", "siteTitle": "CA Technologies Developer Network", "lastUpdated": 1501784674317, "color": { "siteTitle": "#48575F", "pageTitle": "#48575F", "background": "#F7F7F7", "bodyText": "#48575F", "link": "#09AEEF", "linkHover": "rgba(9, 174, 239, .5)", "smallText": "#48575F", "borderColor": "#D8D8D8", "primaryButtonBackground": "#09AEEF", "primaryButtonText": "#FFFFFF", "primaryButtonHover": "rgba(9, 174, 239, .5)", "headerBackground": "#FFFFFF", "headerLink": "#09AEEF", "footerBackground": "#48575F", "footerText": "#FFFFFF", "footerLink": "#09AEEF" }, "typography": { "siteTitle": "CA Sans Light", "pageTitle": "CA Sans Light", "bodyText": "Clear Sans", "smallText": "Clear Sans", "footerText": "Clear Sans", "buttonText": "Clear Sans", "custom": [] }, "fontSize": { "siteTitle": "30px", "pageTitle": "25px", "bodyText": "14px", "smallText": "12px", "footerText": "14px", "buttonText": "16px" }, "display": { "versionNumber": true, "copyright": true }, "images": { "backgroundFooterUri": "", "backgroundHeaderUri": "" }, "label": { "service.publish.nav.manageapi.title": "APIs", "service.publish.nav.apps.title": "Apps", "service.publish.nav.apiexplorer.title": "API Explorer" } } }, "SignUpRequest": { "type": "object", "properties": { "Email": { "type": "string" }, "OrganizationName": { "type": "string", "description": "Should be unique" }, "OrganizationDescription": { "type": "string" }, "Uuid": { "type": "string" } }, "example": { "Email": "[email protected]", "OrganizationName": "QWdssdc", "OrganizationDescription": "", "Uuid": "{{GENERATED_GUID}}" } }, "SignUpResponse": { "type": "object", "properties": { "d": { "type": "object", "properties": { "__metadata": { "type": "object", "properties": { "uri": { "type": "string" }, "type": { "type": "string" } } }, "OrganizationName": { "type": "string" }, "Uuid": { "type": "string" }, "Email": { "type": "string" }, "FormField": { "type": "string" }, "OrganizationDescription": { "type": "string" } } } }, "example": { "d": { "__metadata": { "uri": "http://apim.dev.ca.com/portal-data/Portal.svc/Registrations('48ad61b0-87b1-4fae-bba1-73e5f3e48df8')", "type": "com.layer7.portal.service.odata.PortalODataProducerFactory.Registration" }, "OrganizationName": "QWdsdc", "Uuid": "48ad61b0-87b1-4fae-bba1-73e5f3e48df8", "Email": "[email protected]", "FormField": null, "OrganizationDescription": "" } } }, "Message": { "type": "object", "properties": { "lang": { "type": "string" }, "value": { "type": "string" } } }, "ErrorBody": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "$ref": "#/definitions/Message" } } }, "Error": { "type": "object", "properties": { "error": { "$ref": "#/definitions/ErrorBody" } }, "example": { "error": { "code": "ServerErrorException", "message": { "lang": "en-US", "value": "Internal Server Error" } } } }, "NavigationListBody": { "type": "object", "properties": { "url": { "type": "string" }, "title": { "type": "string" }, "titleKey": { "type": "string" }, "target": { "type": "string" } } }, "Navigation": { "type": "object", "properties": { "portalAdmin": { "type": "array", "items": { "$ref": "#/definitions/NavigationListBody" } }, "developer": { "type": "array", "items": { "$ref": "#/definitions/NavigationListBody" } }, "account": { "type": "array", "items": { "$ref": "#/definitions/NavigationListBody" } }, "hidden": { "type": "array", "items": { "$ref": "#/definitions/NavigationListBody" } } }, "example": { "portalAdmin": [ { "url": "/admin/app/api-catalog", "title": "API Catalog", "titleKey": "label.appnav.apicatalog", "target": null } ], "developer": [ { "url": "/admin/homeRedirect", "title": "Home", "titleKey": "label.appnav.home", "target": null } ], "account": [ { "url": "/admin/app/registration", "title": "Sign Up", "titleKey": "label.appnav.register", "target": null }, { "url": "/admin/loginRedirect", "title": "Login", "titleKey": "label.appnav.login", "target": null } ], "hidden": [] } }, "passwordPolicyElement": { "type": "object", "properties": { "value": { "type": "integer", "description": "value of the property" }, "enabled": { "type": "boolean", "description": "whether the property is enabled" } } }, "PasswordPolicies": { "allOf": [ { "$ref": "#/definitions/BaseResponseInteger" } ], "type": "object", "properties": { "authScheme": { "type": "object", "properties": { "passwordpolicies": { "type": "object", "properties": { "regexConfig": { "type": "object", "properties": { "MINIMUM_LENGTH": { "$ref": "#/definitions/passwordPolicyElement" }, "SYMBOL": { "$ref": "#/definitions/passwordPolicyElement" }, "NUMBER": { "$ref": "#/definitions/passwordPolicyElement" }, "REGEX": { "type": "object", "$ref": "#/definitions/passwordPolicyElement" }, "UPPERCASE": { "$ref": "#/definitions/passwordPolicyElement" }, "MAXIMUM_LENGTH": { "$ref": "#/definitions/passwordPolicyElement" }, "LOWERCASE": { "$ref": "#/definitions/passwordPolicyElement" }, "SUPPORTED_SYMBOLS": { "$ref": "#/definitions/passwordPolicyElement" } } }, "passwordConfig": { "type": "object", "properties": { "PASSWORD_HISTORY": { "$ref": "#/definitions/passwordPolicyElement" }, "PASSWORD_EXPIRY": { "$ref": "#/definitions/passwordPolicyElement" } } } } } } } }, "example": { "respCode": 200, "respMsg": "Successfully fetched Password Policies", "authScheme": { "passwordPolicies": { "regexConfig": { "MINIMUM_LENGTH": { "value": 8, "enabled": true }, "SYMBOL": { "value": 1, "enabled": true }, "NUMBER": { "value": 1, "enabled": true }, "REGEX": { "value": "^(?=(.*[a-z]){1})(?=(.*[[email protected]#$%^&*-]){1})(?=(.*[A-Z]){1})(?=(.*[0-9]){1})[ [email protected]#$%^&*-]{8,60}$", "enabled": true }, "UPPERCASE": { "value": 1, "enabled": true }, "MAXIMUM_LENGTH": { "value": 60, "enabled": true }, "LOWERCASE": { "value": 1, "enabled": true }, "SUPPORTED_SYMBOLS": { "value": "[email protected]#$%^&*-", "enabled": true } }, "passwordConfig": { "PASSWORD_HISTORY": { "value": 5, "enabled": false }, "PASSWORD_EXPIRY": { "value": 60, "enabled": false } } } } } }, "ResultResponse": { "type": "object", "properties": { "d": { "type": "object", "properties": { "result": { "type": "boolean" } } } }, "example": { "d": { "result": true } } } } }
Prerequisites for Re-customization
You do not need to remove an existing bundle to upload a new one. System allows you to upload another bundle, while the existing one is still in use. Consider the following points for re-customization:
  • You cannot upload more than two bundles. To add one more bundle, delete the bundle that is not in use.
  • Recommendation:
    Use a different html filename every time you apply the customization on the same page. For example, if you have used home.html for the initial customization, then use home1.html for the subsequent customization. This process ensures that the page caching is considerably improved and the changes are reflected faster.
  • Recommendation:
    Keep a backup of your previous customization, if necessary.
Start Customizing
  1. To use the templates, download and unzip "SampleTemplates.zip" from
    Content Management, Manage Custom Pages, Upload Page Bundles.
    1. Go to
      <PageName>
      .
      The folder contains the html, js, and css files.
    2. Depending on your organization's needs, customize the files. Read the APIs that are applicable for the page that you want to customize.
    3. Save your changes.
  2. Create a zip file with all the contents that you need for customization.
  3. From
    Upload Page Bundles
    , select
    Upload Select Upload ZIP Bundle
    to upload this zip file.
    If you have already uploaded two bundles, you have to delete an unpublished bundle to upload a new one.
  4. Select the html file from the
    <PageName>
    drop down. For example, if you are customizing the Home page, select the Home drop-down.
    All the assignments should be from a single bundle; pages from different bundles cannot be saved.
  5. Select
    Save & Publish
    . Selecting
    Cancel
    restores the previous customization, but the recently uploaded bundle remains in the Source Bundle drop down.
    Consider the following points after you have customized:
    • The bundle status changes to "Published" as shown in the following screenshot.
      Cust.png
    • You have selected a bundle, but assigned and saved all the pages to portal default. The selected bundle becomes unpublished.
    • The Delete Bundle link does not appear when you select a published bundle from the Source Bundle drop down.
Reset to Default Settings
Select
None
from Source Bundle drop down and save your changes. All the pages are reset to default portal pages and the published bundle becomes unpublished.
Delete a Bundle
You can only delete a bundle that is unpublished (not in use).
Follow these steps:
  1. Select the bundle that is not in use from
    Source Bundle
    .
  2. Select
    Delete Bundle
    .
  3. Select
    Delete
    .
FAQs
  • I have customized a page. How do I revert to the default page?
    You can select the "default" option from the drop-down.
  • To re-customize the pages, I uploaded a new bundle. I selected the pages from the drop-down. But I did not save the changes and navigated to another page. Will the older customization be retained?
    Yes. Customization does not change until you publish or save the changes. Similar applies when the Content Management page times out before you save the changes.
  • I customized a page using a file, but the changes are not reflecting immediately or are taking longer than expected. What do I do?
    This problem occurs because of caching. You may have used the same filename when reapplying the customization. The resources are updated, but the dispatcher still serves the old resources. It might take an hour to serve the updated content due to caching on dispatcher.
    To force the dispatcher to serve the updated content instantly, the Portal administrator can restart the dispatcher container.
    API Portal is unavailable while the dispatcher restarts.
    Now, when the dispatcher starts serving updated pages, you still might not see the updated content. This is because of web browser caching and might take a day to show the newer version. Clear the cached assets for the API Portal site or open the site in private or incognito mode.
  • I applied the changes to the Login page and I can see the customizations. But something went wrong in this page, because I am unable to relogin and fix the changes. How do I go back to the default Login page?
    This issue might have happened because you modified the
    main.js
    file incorrectly. Ensure that you read the APIs before attempting to change the code. To go back to default Login page, enter http://<portal.ca.com>/admin/login into your web browser.