Direct Render PIN-Set Procedure

This guide describes the direct render procedure for setting PINs, using the Get Card PIN Change Key and Commit Card PIN Change endpoints. This procedure transfers PCI-sensitive information directly from the cardholder’s device to Galileo's system using a PIN-set form that Galileo hosts. You do not need to be PCI compliant to use this method.

Go to PIN-Set Procedures for other methods.

Use this procedure to:

  • Set a cardholder’s PIN for a new card
  • Reset a cardholder's PIN for an existing card

The direct form PIN-change process transfers PIN data from the cardholder directly to Galileo without the data passing through your system, thereby satisfying information security requirements. The process involves the following high-level steps:

  1. You call the Galileo Program API to get a PIN-change access key.
  2. You present the cardholder with an HTML PIN-set form that Galileo hosts.
  3. The cardholder enters the PIN twice and submits the form. Galileo stages the change if the PINs are correct.
  4. Galileo informs you of the success or failure of the PIN validation and form submission via either JavaScript or redirect pages, and Events API webhook messages may also be sent.
  5. If successful, you call the Galileo Program API to commit the PIN change. Galileo may send an Events API webhook to notify that the change was successful.


You will need to decide among various options before using this procedure.

  • PIN-set form presentation:
    • WebView — Wrap the PIN-set form in a WebView.
    • Browser window/pop-up — Present the PIN-set form directly in a browser or pop-up.
    • iFrame — Embed the PIN-set form as an iFrame.
  • PIN-set form styling:
  • Results presentation:
    • Your redirect pages — You can host one page for both results or different pages for success and failure. The pages can be accessed via HTTP or a deep link in your app.
    • Galileo redirect pages — Galileo hosts the success and failure pages.
    • JavaScript — Galileo enables JavaScript callbacks to be called on the error and success pages. JavaScript must be enabled on the PIN-set form.
    • Webhook messages — Galileo sends Events API webhook messages to your server in addition to one of the other methods.
  • Token/key validity:
    • Amount of time — Default is five minutes.
    • Number of attempts — Default is five attempts.

Prior setup

After you have been approved to use the direct render procedure, you must coordinate with Galileo to get set up. You will need to provide:

  • Issuing bank approval.
  • If using the redirect options — A list of base URLs to be used in redirects. When you pass in a redirect URL, the beginning of the URL is matched to the configured URLs in the Galileo system. You may also use custom schemes to intercept redirects within a mobile application.
    • If the success redirect URL is, Galileo must register in the system to allow the redirect.
    • If you are using a failure redirect URL and it shares the same base URL (e.g.,, no additional base URLs need to be registered.
    • If using a mobile deep link such as bar://pin-success, Galileo must register bar://.
  • Additional header fields and values to be set on the redirect response.
  • Whether to enable mobile callbacks in WebView.
  • Whether to enable JavaScript messages in the parent page for the iFrame.
  • If using the iFrame option — A list of URLs that will be embedding the iFrame. Because some legacy browsers do not support Content-Security-Policy, the first domain listed will be used for the X-Frame-Options header field.
    • If the URL of the site embedding the iFrame is, Galileo registers to enable the PIN form site to be in an iFrame.
  • CSS (cascading stylesheet) or SCSS (sassy CSS).


All stylesheets must be approved by Galileo before they are added to the system. You can provide more than one stylesheet. The filenames for the stylesheets are specified in a comma-delimited list in the GGSAS parameter, with the first filename listed being the default stylesheet. For example, if you create three stylesheets, they would be listed as style-1,style-2,style-3 in the GGSAS parameter. See step 3. Call the PIN-set form for instructions on specifying the stylesheet.

Galileo will provide you with a starting CSS/SCSS file to style the PIN-set form. You then modify the file to add your styling. (There are SCSS plugins available for most major IDEs including Visual Studio Code and Jetbrains IDEs.)



You can provide or update the stylesheet at any point in the process. Galileo can perform initial setup without your stylesheet. When submitting a stylesheet change, you must provide the entire stylesheet.

The top section of the SCSS file has variables used for the form and basic styling. Most styles can be modified by setting the variables in the first section.

If you need more advanced styling, Galileo can provide four sample HTML pages that match the HTML of the PIN-set form:

  • Set Your Pin.html — The initial PIN-set form with no alerts or errors.
  • Set Your Pin-form-errors.html — The initial PIN-set form with form errors and error alerts visible.
  • Set Your Pin-error.html — The error page that the cardholder would see if a token becomes expired or other system error occurs, such that you need to restart the process.
  • Set Your Pin-success.html — The success page that the cardholder would see

You cannot edit the HTML pages — the only styling that is permitted is via the stylesheet. If you are using redirects, the sample error and success pages will not be visible to your cardholder. Galileo will redirect to the URLs that you passed instead of displaying the sample pages.



The stylesheet cannot include references to external resources such as images, fonts, or additional stylesheets. The CSS/SCSS file can contain small base64-encoded images, which must be approved and encoded by Galileo.

Galileo has several fonts available, listed on the Supported Fonts page. If you want to use other fonts, you must first obtain a license to use the font, then the font must be approved and go through a project request and change window (at least one month), so additional costs may accrue.

To use one of these fonts, add the font face to your CSS/SCSS file. For example:

@font-face {
    font-family: 'Roboto Condensed';
    font-style: normal;
    font-weight: 400;
    src: url('/agserv/fonts/roboto-condensed-v18-latin-regular.eot');
    src: local('Roboto Condensed'), local('Roboto Condensed Regular'), 
url('/agserv/fonts/roboto-condensed-v18-latin/roboto-condensed-v18-latin-regular.eot#iefix') format('embedded-opentype'),
url('/agserv/fonts/roboto-condensed-v18-latin/roboto-condensed-v18-latin-regular.woff2') format('woff2'),
url('/agserv/fonts/roboto-condensed-v18-latin/roboto-condensed-v18-latin-regular.woff') format('woff'),
url('/agserv/fonts/roboto-condensed-v18-latin/roboto-condensed-v18-latin-regular.ttf') format('truetype'),
url('/agserv/fonts/roboto-condensed-v18-latin/roboto-condensed-v18-latin-regular.svg#RobotoCondensed') format('svg');

Once you have added your styles, Galileo will add the CSS/SCSS file or files to the system. (The stylesheets replace the partner.css file in the sample HTML pages.)



If you submit stylesheet changes but they are not visible after Galileo has updated the CSS file, verify that your submitter_id is correct. CSS files are linked to the submitter_id, so if there is a typo you will most likely see the default CSS.


If you are wrapping the PIN-set form in a native mobile application WebView, you can add an interface/message handler to receive the code from the error and success pages.

JavaScript must be enabled on the Galileo system. Interfaces are called onLoad if interfaces are found in code on error and success pages.

For Android, generate and register to the WebView a JavaScriptInterface with the name Android and the method postMessage(int statusCode). See Sample code for an example.

For iOS, generate and register to the WebView a ScriptMessageHandler with the name IOS. See Sample code for an example.

Direct render PIN-set workflow

This flowchart illustrates the workflow for the process:

1. Cardholder accesses your interface

The cardholder goes to your interface to set or change a PIN.

2. Send the Get Card PIN Change Key call

Galileo recommends that you pass the CAD (card_id) for accountNo in the Get Card PIN Change Key call.

In the response, Galileo sends a 50-character key in the token field. This key is valid for only a limited time and for only a specified number of uses, which are configured in your provider parameters. Defaults are five minutes and five page requests. The key cannot be reused after a success.

Consult the Get Card PIN Change Key endpoint for status codes and next steps, if any.

3. Call the PIN-set form

Create a URL using the token, your submitter ID, and locale to call the PIN-set form. The PIN-set form that you call for the customer's initial PIN set will be identical to the customer's subsequent calls to reset the PIN.

The URL in the example is an AWS instance that Galileo sets up for each client. Request an AWS URL from Galileo if you do not already have one. The example contains the URL for the CV environment. For Production change cv in the URL to pd.

<iframe src=\"https://agserv-[clientname][locale]/[submitter id]/[token]">


  • clientname — Your Galileo system name
  • locale — Supported locales are en_US, es_US, fr_US, fr_CA, en_MX, es_MX, or pt_BR. You can specify languages as en, es, or fr, however pt_BR cannot be shortened to pt.
  • submitter_id — Supplied by Galileo, this number identifies your stylesheet, which will be applied to the PIN-set form. The identifier has the format [provider_id]-9999.
  • token — The 50-character token that you retrieved by calling Get Card PIN Change Key.

Display multiple languages in PIN-set form

You can display English and Spanish instructions on the PIN-set form using one stylesheet.

To do so, you pass en or es in the locale parameter with the Pin-set form call. We also support specifying the language using en_* and es_*. Please refer to Galileo’s default CSS/SCSS and update the defined variables as applicable. For example:

$en-partner-header-content: "";
$en-partner-sub-header-content: "";
$en-partner-instructions-content: "Please use the form below to set your PIN";
$en-set-pin-label-content: "Please enter your PIN";
$en-set-pin-placeholder: "PIN";
$en-set-pin-confirm-label-content: "Please re-enter your PIN";
$en-set-pin-confirm-placeholder: "Re-enter PIN";
$en-submit-button-content: "Submit";
$en-success-instructions: "";

$es-partner-header-content: "";
$es-partner-sub-header-content: "";
$es-partner-instructions-content: "Utilice el siguiente formulario para cambiar su PIN";
$es-set-pin-label-content: "Escribe el PIN";
$es-set-pin-placeholder: "PIN";
$es-set-pin-confirm-label-content: "Escribe el PIN de nuevo";
$es-set-pin-confirm-placeholder: "PIN";
$es-submit-button-content: "Enviar";
$es-success-instructions: "";
$en-partner-instructions-content: "Utilice el siguiente formulario para establecer su PIN"; 
$es-partner-instructions-content: "Utilice el siguiente formulario para establecer su PIN";

Include redirects (optional)

If you are redirecting to pages that you host, you can specify one page for both results or different pages for success and failure.

You must pass in the URLs with the PIN-set form call, using this format as well as URL encoding:

?r=[URL]URL is the single redirect page or the success redirect page.
?f=[URL]URL is the failure redirect page.

Single-page redirect

This is the format when both success and failure use the same page:


Optional: Include the s parameter to specify which stylesheet to use, such as s=style2. If you do not pass the s parameter, the first stylesheet listed in the GGSAS parameter is used.

Separate-page redirect

This is the format when success and failure each have their own page:


Optional: Include the s parameter to specify which stylesheet to use, such as s=style1. If you do not pass the s parameter, the first stylesheet listed in the GGSAS parameter is used.


If you add %status_code% to the redirect URL, it will be replaced with the status code; otherwise, status_code=[status_code] will be appended to the redirect URL as a query-string variable. If the redirect URL contains variables, ensure that the variables are URL-encoded before encoding the full URL.

Consult the PIN-set form status codes table to see an explanation of the status codes for the PIN-set form call and which next steps to take, if any.

4. Cardholder submits the form

The cardholder enters and re-enters the PIN and submits the data directly to Galileo, without the data traversing your system.

5. Galileo sends the verdict

If submitting the form times out, Galileo sends a failure message. If submitting the form is otherwise unsuccessful, such as the form being incorrectly formatted, Galileo sends a failure message. See PIN-set form status codes for more information.

If the form submission is successful, Galileo performs two verification checks:

  • The PINs have four digits each
  • The PINs match

Galileo responds with either success or failure, sending that response via redirect or JavaScript.

If the verification checks are successful, Galileo stages the PIN change. According to your arrangements with Galileo, you will also receive the AFPE: agserv_PIN_change_fail or AFPS: agserv_PIN_change_success Account Events webhooks.

6. Send the Commit Card PIN Change call

If you receive a success message, send the Commit Card PIN Change call to commit the change. Use the same accountNo that you used for the Get Card PIN Change Key call.

Consult the Commit Card PIN Change endpoint for status codes and next steps.

When the PIN change is successful, Galileo sends the PNCH: system_pin_change event. At this point, the cardholder can use the PIN, and you can retrieve the PIN via the PIN Retrieval Service if you are subscribed to that service.

Sample code

The samples below are provided as a reference on how to consume iFrame messages and mobile callbacks.



The code samples contain some debugging and logging code that should not be used in the Production environment.


Requires JavaScript and iFrame messaging to be enabled.

if (window.addEventListener) {
	window.addEventListener("message", function (event) {
    	// Modify URL to match environment
    	if (event.origin !== "") {
        	console.log("Event.origin does not match baseurl");
    	var statusCode =;
    	// Do something with the statusCode
    	console.log("Received status code: " + statusCode);
    	alert("Received message: " +;
	}, false);

Android (Kotlin)

Requires JavaScript and mobile callbacks to be enabled.

class MainActivity : AppCompatActivity() { 
	lateinit var webView: WebView
	override fun onCreate(savedInstanceState: Bundle?) {
    	webView = WebView(this)
    	webView.settings.javaScriptEnabled = true
    	webView.addJavascriptInterface(WebAppInterface(this), "Android")
    	webView.webChromeClient = WebChromeClient()
    	webView.webViewClient = WebViewClient()
	override fun onResume() {
	class WebAppInterface(private val context:Context) {
    	fun postMessage(code: Int) {
        	Toast.makeText(context, "Received code $code", Toast.LENGTH_LONG).show()

iOS (Swift)

Requires JavaScript and mobile callbacks to be enabled.

class ViewController: UIViewController, WKScriptMessageHandler, WKNavigationDelegate {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    override func viewDidLoad() {
        let preferences = WKPreferences();
        preferences.javaScriptEnabled = true;
        let contentController = WKUserContentController();
        contentController.add(self, name: "IOS");
        let config = WKWebViewConfiguration();
        config.preferences = preferences;
        config.userContentController = contentController;
        let url = URL(string: "");
        let webview = WKWebView(frame:
            self.view.bounds, configuration: config); self.view.addSubview(webview);
        webview.navigationDelegate = self
        webview.load( URLRequest( url: url!) );
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
                                   completionHandler: { (html: Any?, error: Error?) in

Galileo setup

These internal provider-level parameters must be set at Galileo, according to the form-presentation and results-presentation methods that you are using.

GGEJSEnable all JavaScript. Required if using mobile or iFrame postMessage.iFrame
GGHDR (optional)A set of key/value pairs for additional response headers when using no-redirect mode.iFrame
GGIFDDomains that are allowed to call the iFrame.iFrameRedirect
GGIFMEnable event trigger on error and success pages.iFrameJavaScript
Number of times a PIN-set token can be used. Default: 5iFrame
Seconds before token expiry. Default: 300iFrame
GGMCBEnable native mobile callbacks.WebViewJavaScript
GGRBUArray of redirect URLs when using a single results page or base redirect URLs when using both success and failure redirect pagesiFrame
GGSASName of the file to use as a stylesheet. In the case of multiple stylesheets, this is a comma-separated list of filenames.iFrame

PIN-set form status codes

Consult this table to see an explanation of the status codes for the PIN-set form call and which next steps to take, if any.

Status codeDescriptionNext steps
0SuccessContinue the procedure
-1Bad submitter ID or no redirect URL providedRetry with valid submitter ID or provide redirect URL
-10Invalid token. Token is either expired or not found.Verify that the token is correct or call the Get Card PIN Change Key endpoint again.
-11Cardholder submitted a form with a token that is no longer valid, because Get Card PIN Change Key was called again, invalidating the previous key.Verify that the form is using the correct key before calling Get Card PIN Change Key again.
-999System errorContact Galileo for troubleshooting
-9999Unknown errorContact Galileo for troubleshooting