# HostedPCI (HPCI) Integration Guide

> **What this file is:** a self-contained, machine-readable reference for integrating with
> HostedPCI. Paste it into your AI coding assistant (Claude, ChatGPT, Cursor, Copilot, etc.)
> so it has full context on the HostedPCI iFrame and Payment API when helping you build your
> integration.
>
> **Audience:** developers integrating a merchant/e-commerce site with HostedPCI.
> **Not covered here:** account-specific values (site IDs, API keys, host names, payment
> profile names) — those are provided by HostedPCI when your account is activated.
>
> For the human-readable version with screenshots and every gateway-specific parameter, see
> https://www.hostedpci.com/documentation

---

## 1. What HostedPCI does

HostedPCI removes credit-card and bank-account data from your systems so your PCI scope
drops (typically from **SAQ D**, ~400 questions, to **SAQ A**, ~11 questions).

The model has two surfaces:

1. **iFrame (client-side capture)** — a HostedPCI-hosted iframe renders only the in-scope
   fields (card number + CVV, or ACH routing/account). The raw values never touch your page.
   On submit, the iframe returns **tokens** to your checkout form.
2. **Payment API (server-side)** — your backend sends those tokens (never the real PAN) to
   HostedPCI over HTTPS to authorize, capture, sale, void, credit, tokenize, or run ACH.

**Token lifetime:** an HPCI token stays active for **18 months from the last time it is used**.

```
Customer browser                         Your server                 HostedPCI
────────────────                         ───────────                 ─────────
[HPCI iframe] --card entry--> tokenize --------------------------------> vault
      │  returns ccNum/ccCVV/ccBIN tokens
      ▼
[your checkout form] --POST tokens--> [your backend] --Payment API (NVP)--> gateway
```

---

## 2. Prerequisites (provided by HostedPCI on activation)

| Item | Description |
|---|---|
| `hpciSiteId` (a.k.a. `sid`) | Numeric site id. **Different for staging vs live.** |
| `location` / `locationName` | Location reference configured in the HPCI customer portal. |
| iFrame host | e.g. `https://ccframe.hostedpci.com` (use the exact host HPCI gives you). |
| API host (`HPCI_API_HOSTNAME`) | Base URL for server-side Payment API calls. |
| API `userName` | Payment API user id. |
| API `userPassKey` | Payment API pass key. **Server-side only — never expose in the browser.** |
| Payment profile (`txnPayName`) | Name of the payment/gateway profile. Default is `DEF`. Pre-arranged with HPCI. |

---

## 3. iFrame Integration (client-side card capture)

### 3.1 Include the library

Three scripts, **in this order**, with Sub-Resource Integrity (SRI) hashes. HPCI may rotate
the scripts (~every 3 months) and will send you updated `integrity` hashes — keep them current
or the payment flow breaks.

```html
<script src="https://ccframe.hostedpci.com/WBSStatic/site60/proxy/js/jquery-3.4.1.min.js?v=101"
        type="text/javascript" charset="utf-8"
        integrity="sha384-vk5WoKIaW/vJyUAd9n/wmopsmNhiy+L2Z+SBxGYnUkunIxVxAv/UtMOhba/xskxh"
        crossorigin="anonymous"></script>
<script src="https://ccframe.hostedpci.com/WBSStatic/site60/proxy/js/jquery.ba-postmessage.2.0.0.min.js?v=101"
        type="text/javascript" charset="utf-8"
        integrity="sha384-qBKdSvHrjvII0DmlSz4V3ylhR09JGljAiyeCnuOhPLXAzsXSzLd9EBn3ipf3clDN"
        crossorigin="anonymous"></script>
<script src="https://ccframe.hostedpci.com/WBSStatic/site60/proxy/js/hpci-cciframe-1.0.js"
        type="text/javascript" charset="utf-8"
        integrity="sha384-XO2Gt7i0tf/8gSEeyrjMGllZfXUsA7zPtXwsSN7IML4QKmiRwqObOmdakgRz621r"
        crossorigin="anonymous"></script>
```

### 3.2 Global configuration variables

These MUST be global (declared at top-level script scope, i.e. on `window`). The library
`hpci-cciframe-1.0.js` reads them by name; if they are trapped inside a function/module scope
the library throws a `ReferenceError`.

```js
// Must match the iframe src host / URL
var hpciCCFrameHost    = "https://ccframe.hostedpci.com";
var hpciCCFrameName    = "ccframe"; // the name attribute of the iframe element
var hpciCCFrameFullUrl = "https://ccframe.hostedpci.com/iSynSApp/showPxyPage!ccFrame.action?pgmode1=prod&locationName=[location]&sid=[hpciSiteId]&enableEarlyToken=Y&enableTokenDisplay=Y&reportCCType=Y&reportInit=Y&strictMsgFmt=Y&fullParentHost=[yourHost]&fullParentQStr=[yourPagePathAndQuery]";
```

### 3.3 The iframe element

Modern (CSP-friendly) install — no inline `onload`:

```html
<iframe id="ccframe" name="ccframe"
  src="https://ccframe.hostedpci.com/iSynSApp/showPxyPage!ccFrame.action?pgmode1=prod&enableEarlyToken=Y&enableTokenDisplay=Y&reportCCType=Y&reportInit=Y&strictMsgFmt=Y&locationName=[location]&sid=[hpciSiteId]&fullParentHost=[yourHost]&fullParentQStr=[yourPagePathAndQuery]&formatCCDigits=Y&formatCCDigitsDelimiter=-"
  frameborder="0" height="300px" scrolling="NO">
  If you can see this, your browser doesn't understand IFRAME.
</iframe>
```

Then wire the load event in a script (instead of inline `onload="receiveHPCIMsg()"`):

```js
document.getElementById("ccframe").addEventListener("load", receiveHPCIMsg);
```

> **Legacy install** (simpler, if CSP isn't a concern): keep `onload="receiveHPCIMsg()"` on the
> `<iframe>` tag and `onclick="return sendHPCIMsg();"` on the submit button. Both approaches work.

### 3.4 The checkout form (hidden token fields)

The iframe writes token values back into these hidden inputs on your form:

```html
<form id="CCAcceptForm" action="https://yoursite/checkoutAction" method="post">
  <input id="ccNum" name="ccNum" type="hidden" value=" " />   <!-- card-number token -->
  <input id="ccCVV" name="ccCVV" type="hidden" value=" " />   <!-- CVV token -->
  <input id="ccBIN" name="ccBIN" type="hidden" value=" " />   <!-- card BIN (first digits) -->
  <input name="action3DSec" type="hidden" value="verifyenroll" /> <!-- only if using 3D Secure -->
  <button id="submitButton" type="submit">Process Payment</button>
</form>
```

| Field | Purpose |
|---|---|
| `ccNum` | HPCI token representing the credit card number |
| `ccCVV` | HPCI token representing the CVV |
| `ccBIN` | BIN (Bank Identification Number) of the card |
| `action3DSec` | Only for 3D Secure — passed to the API as `pxyThreeDSecAuth.actionName` |

`ccNum` + `ccCVV` are the minimum. Expiry, billing info, amount, etc. are added by your own
form fields and sent to the Payment API server-side.

### 3.5 Success & error handlers

Define these globally. The success handler receives the tokens and typically copies them into
the hidden fields then submits the form. Use the handler version matching your iFrame version
(V9 shown — the fullest; requires V6 iFrame). **The library calls whichever versions you define.**

```js
var hpciSiteErrorHandler = function (errorCode, errorMsg) {
  console.log("HPCI error " + errorCode + ": " + errorMsg);
};

var hpciSiteSuccessHandlerV9 = function (
    hpciMsgSrcFrameName, hpciMappedCCValue, hpciMappedCVVValue, hpciCCBINValue,
    hpciGtyTokenValue, hpciCCLast4Value, hpciReportedFormFieldsObj, hpciGtyTokenAuthRespValue,
    hpciTokenRespEncrypt, threeDSValuesObj, hpciCCTypeValue,
    hpciMappedACHValue1, hpciMappedACHValue2, hpciMappedACHValue3, hpciMappedACHValue4) {
  document.getElementById("ccNum").value = hpciMappedCCValue;
  document.getElementById("ccCVV").value = hpciMappedCVVValue;
  document.getElementById("ccBIN").value = hpciCCBINValue;
  document.getElementById("CCAcceptForm").submit();
};
```

### 3.6 Submitting the iframe

Call `sendHPCIMsg()` to tell the iframe to tokenize and post its values back to your form. On
success your `hpciSiteSuccessHandler*` fires; on failure `hpciSiteErrorHandler` fires.

```js
document.getElementById("submitButton").addEventListener("click", function (event) {
  if (!sendHPCIMsg()) event.preventDefault(); // stop submit if tokenization didn't start
});
```

Library functions you'll use: `sendHPCIMsg()` (trigger tokenize+submit), `receiveHPCIMsg()`
(wire to the iframe `load` event), and `receivePINMsg()` (3DS PIN flow).

### 3.7 Content Security Policy (nonce)

If your site enforces CSP, generate a per-request nonce and apply it to the CSP meta tag and
every `<script>`:

```js
function generateNonce() {
  return crypto.randomUUID().replace(/-/g, '').substring(0, 8);
}
const scriptNonce = generateNonce();
```

```html
<meta http-equiv="Content-Security-Policy"
      content="script-src https://ccframe.hostedpci.com 'self' 'nonce-GENERATED_DYNAMIC_NONCE';">
<script nonce="GENERATED_DYNAMIC_NONCE"> /* your JS */ </script>
```

### 3.8 iFrame `src` parameter reference

Appended to `.../iSynSApp/showPxyPage!ccFrame.action?...`

| Parameter | Meaning |
|---|---|
| `pgmode1` | Mode, e.g. `prod`. |
| `locationName` | Location reference (prerequisite). |
| `sid` | HPCI site id (prerequisite). |
| `fullParentHost` | Full hostname of the parent page hosting the iframe. |
| `fullParentQStr` | The current page path + query string (must match the browser address bar; used as a fallback for browsers without postMessage). |
| `enableEarlyToken` | `Y` = generate the token as soon as a valid card is entered (before submit). Fires the preliminary handlers. |
| `enableTokenDisplay` | `Y` = show the stored masked value pre-populated in the field. |
| `reportCCType` | `Y` = report card type/BIN/validity/length once the user leaves the field (fires `hpciCCPreliminarySuccessHandler*`). |
| `reportCCDigits` / `reportCVVDigits` | `Y` = keypress feedback from the card/CVV field (requires iFrame V2+). |
| `formatCCDigits` / `formatCCDigitsDelimiter` | Auto-format the card number; delimiter must be URL-encoded (`%20` / `-` / `_`). |
| `formatCCMaskMode` / `formatCCMaskChar` | Masking, e.g. `S6X6` masks the middle 6 digits; char is `*` or `X` (requires V4/V5). |
| `reportFormFields` | Extra iframe fields to report, `;`-separated, e.g. `nameoncard;expiryMonth;expiryYear` (fires `hpciFormFieldPreliminarySuccessHandler`). |
| `reportInit` | `Y` = fire `hpciInitCompleteSuccessHandler*` when the iframe is initialized. |
| `strictMsgFmt` | `Y` = strict message format. |
| `enable3DSec` | Enables 3DS 2.0 iFrame. Value depends on provider, e.g. `cruise1`, `wpflex1`, or `waitbin` (delays 3DS init), or `skip3ds`. |
| `selected3DSecPayName` / `selected3DSecPayCCType` / `selected3DSecPayCurISO` | 3DS payment profile name / card type / currency (`any` allowed). |
| `ccNumTokenIdx` | Which iframe index to use — set `1` unless loading multiple iframes on one page (required for CVV-only iframe). |
| `ccNumToken` | Card token associated with a CVV iframe (to re-tokenize CVV). |
| `dataType` | `achus1` enables ACH tokenization (requires V6 / V6Dev). |
| `lang` | `fr_CA` for the French iframe. |
| `pluginMode` / `jqVersion` | jQuery version control (`jq1`/`jq2`/`jqdef`/`jq3`; requires V2+). |
| `browserType` / `clientType` | `mobile` or `def`. |
| `cvvValidate` | `Y` = basic CVV validation (numeric, 3–4 chars). |

### 3.9 Callback / handler reference

Handlers are versioned; higher versions return everything the lower ones do plus more. Define
the version that matches your enabled iFrame version.

| Handler | Returns / purpose |
|---|---|
| `hpciSiteSuccessHandler` … `V9` | Successful tokenization. `V2` adds BIN; `V3` adds gateway token; `V4` adds last4/auth-resp/encrypt; `V5` adds reported form fields; `V6` adds src frame name; `V7` adds `threeDSValuesObj` (3DS: `threeDSOrderId`, `cruiseBinStatus`, `cruiseSessionId`); `V8` adds card type; **`V9` adds ACH values** `hpciMappedACHValue1..4` (requires V6 iFrame). |
| `hpciSiteErrorHandler(errorCode, errorMsg)` | Tokenization/mapping error. |
| `hpciCCPreliminarySuccessHandler` … `V6` | Early card feedback (with `reportCCType`/`enableEarlyToken`). Signature order: card type, BIN, validity flag, length; higher versions add entered length, mapped tokens, form fields, frame name, card type. |
| `hpciCVVPreliminarySuccessHandler` … `V6` | Early CVV feedback (CVV length, valid flag, and — with early token — mapped tokens). |
| `hpciACHPreliminarySuccessHandlerV1(frameName, ach1, ach2, ach3, ach4, tokenRespEncrypt, formFieldsObj)` | Early ACH tokens (requires V6 iFrame). |
| `hpciFormFieldPreliminarySuccessHandler(fieldName, fieldValue)` | Value of extra fields declared in `reportFormFields`. |
| `hpciInitCompleteSuccessHandler` / `V2` | Fires when iframe is initialized (needs `reportInit=Y`). |
| `hpci3DSitePINSuccessHandler` / `hpci3DSitePINErrorHandler` | 3D Secure PIN validation success/error. |
| `hpciSetup3DSSuccessHandler` | Fires when the 3DS iframe is populated. |
| `hpciCCDigitsSuccessHandler*` / `hpciCVVDigitsSuccessHandler*` | Keypress feedback (requires V2+). |

Other helpers: `sendHPCIChangeClassMsg(elementId, class)`, `sendHPCIChangeStyleMsg(elementId, prop, value)`,
`sendHPCIChangeTextMsg(elementId, text)`, and `sendHPCISet3DSecParamMsg("cruise1","DEF_3DSEC","any","any")`
(used during the 3DS `waitbin` flow). If you hit `TypeError: $ is not a function`, set
`hpciNoConflict = "N"` inside `DOMContentLoaded`.

### 3.10 iFrame versions & variants

- **V4** — mapped CC/CVV tokens, BIN, last4, keypress feedback, formatting, masking, early tokenization, report form fields, TLS 1.2.
- **V5** — everything in V4 + masking (`formatCCMaskMode=S6X6`) + 3DS 2.0 `waitbin`.
- **V6 (latest)** — everything in V5 + **ACH tokenization** (`dataType=achus1`, tokens via `hpciSiteSuccessHandlerV9` / `hpciACHPreliminarySuccessHandlerV1`).
- **Basic iFrame** — card number + CVV only.
- **Interactive iFrame** — adds keypress feedback (card-type icons, live validation).
- **Multi-iframe** — multiple iframes on one page (use `ccNumTokenIdx`).
- **CVV-only / PAN-only** — single-field iframes.

### 3.11 ACH tokenization (iFrame)

Add `dataType=achus1` to the iframe `src` (V6/V6Dev required). Instead of card fields the
iframe collects **bank routing + account number** and returns ACH tokens. Read them in
`hpciACHPreliminarySuccessHandlerV1` (early) and/or `hpciSiteSuccessHandlerV9` (final) via the
`hpciMappedACHValue1..4` arguments. Those tokens are then used in the ACH Payment API call
(`pxyACHRecord.bankABANumber` = routing token, `pxyACHRecord.bankAccountNumber` = account token).

---

## 4. Payment API (server-side)

### 4.1 Basics

- Calls are **HTTPS POST** to `HPCI_API_HOSTNAME/iSynSApp/<action>.action`.
- Body is **NVP (Name-Value Pairs)**: `key=value&key=value…`, **URL-encoded, UTF-8**.
- Works from any language that can make HTTPS calls (Java, PHP, C#/.NET, Node, Python…).
- **The card number you send is the HPCI token, not the real PAN.**

### 4.2 Always-required parameters

| Parameter | Value |
|---|---|
| `apiVersion` | `1.0.1` |
| `apiType` | `pxyhpci` |
| `userName` | API user id |
| `userPassKey` | API pass key (server-side only) |
| `pxyTransaction.txnPayName` | Payment profile name (default `DEF`) |

### 4.3 Endpoints

| Transaction | Endpoint |
|---|---|
| Authorize (AUTH) | `/iSynSApp/paymentAuth.action` |
| Capture | `/iSynSApp/paymentCapture.action` |
| Sale (auth + capture) | `/iSynSApp/paymentSale.action` |
| Void | `/iSynSApp/paymentVoid.action` |
| Credit / Refund | `/iSynSApp/paymentCredit.action` |
| Gateway tokenization | `/iSynSApp/paymentGatewayToken.action` |
| ACH submit | `/iSynSApp/paymentACH.action` |
| ACH verify (micro-deposit) | `/iSynSApp/paymentACHVerify.action` |

### 4.4 AUTH — parameters

**Card:**

| Parameter | Value |
|---|---|
| `pxyCreditCard.creditCardNumber` | HPCI **token** for the card |
| `pxyCreditCard.cardCodeVerification` | HPCI **token** for the CVV |
| `pxyCreditCard.expirationMonth` / `.expirationYear` | Card expiry |
| `pxyCreditCard.cardType` | Card type (e.g. `VISA`) |

**Transaction:**

| Parameter | Value |
|---|---|
| `pxyTransaction.txnAmount` | Amount to authorize |
| `pxyTransaction.txnCurISO` | ISO currency (`USD`, `CAD`, `EUR`, …) |
| `pxyTransaction.merchantRefId` | Your order/reference id |
| `pxyTransaction.txnPayName` | `DEF` or a profile name |
| `pxyTransaction.txnComment` | Optional, ≤ 50 chars |
| `pxyTransaction.txnExtraParam1..5` | Gateway-specific extras (ask HPCI) |

**Customer / billing / shipping (as needed):**
`pxyCustomerInfo.email`, `pxyCustomerInfo.customerId`, `pxyCustomerInfo.customerIP`,
`pxyCustomerInfo.billingLocation.{firstName,lastName,address,city,state,zipCode,country,phoneNumber}`,
and the same under `pxyCustomerInfo.shippingLocation.*`. Order: `pxyOrder.{invoiceNumber,description,totalAmount}`.

**AUTH request example** (NVP, one line):

```
apiVersion=1.0.1&apiType=pxyhpci&userName=[API-USER]&userPassKey=[API-PASSKEY]&pxyTransaction.txnPayName=DEF&pxyCreditCard.creditCardNumber=[CARD_TOKEN]&pxyCreditCard.cardCodeVerification=[CVV_TOKEN]&pxyCreditCard.expirationMonth=10&pxyCreditCard.expirationYear=2027&pxyTransaction.txnAmount=45.45&pxyTransaction.txnCurISO=USD&pxyTransaction.merchantRefId=[ORDER-ID]&pxyCustomerInfo.billingLocation.firstName=John&pxyCustomerInfo.billingLocation.lastName=Smith&pxyCustomerInfo.email=john@example.com
```

**AUTH response** (NVP; parse into a map). Key fields to read:

| Response key | Meaning |
|---|---|
| `status` | `success` or `error` |
| `pxyResponse.responseStatus` | e.g. `approved` |
| `pxyResponse.responseStatus.description` | Human-readable result |
| `pxyResponse.processorRefId` | **Save this** — required for Capture/Void/Credit |
| `saleId` / `captureId` / `voidId` / `creditId` | Operation ids |
| `pxyResponse.threeDSAcsUrl` + `pxyResponse.processorType=3dsecResponse` | Indicates a 3DS challenge (see §5) |

### 4.5 Capture / Sale / Void / Credit

- **CAPTURE** captures a prior AUTH. Requires `pxyTransaction.processorRefId` (from the AUTH response) + amount/currency/merchantRefId.
- **SALE** = AUTH + immediate capture (same params as AUTH, different endpoint; no follow-up capture needed).
- **VOID** cancels/reverses using `pxyTransaction.processorRefId`.
- **CREDIT** refunds (partial or full) to the original card using `pxyTransaction.processorRefId`.

**CAPTURE request example:**

```
apiVersion=1.0.1&apiType=pxyhpci&userName=[API-USER]&userPassKey=[API-PASSKEY]&pxyTransaction.processorRefId=[AUTH_REF_ID]&pxyTransaction.txnAmount=45.45&pxyTransaction.txnCurISO=USD&pxyTransaction.merchantRefId=[ORDER-ID]
```

### 4.6 Gateway tokenization

Endpoint `/iSynSApp/paymentGatewayToken.action`. Exchanges the HPCI token for a gateway-native
token. Params: `pxyCreditCard.creditCardNumber` (HPCI token), `pxyCreditCard.cardCodeVerification`,
`pxyCreditCard.expirationMonth/Year`, `pxyTransaction.txnPayName`, and cardholder
`pxyCustomerInfo.billingLocation.firstName/lastName`. Some gateways require extra params — see
the gateway pages in the documentation.

### 4.7 ACH (server-side)

Endpoint `/iSynSApp/paymentACH.action` (and `/iSynSApp/paymentACHVerify.action` for micro-deposit
verification). Enable **ACH Token (Y)** in the payment profile. Currently supported gateways for
ACH: Elavon, IATS, Stripe.

| Parameter | Value |
|---|---|
| `pxyACHRecord.bankABANumber` | Tokenized **routing** number (from the iFrame) |
| `pxyACHRecord.bankAccountNumber` | Tokenized **account** number (from the iFrame) |
| `pxyTransaction.txnPayName` | Profile name |
| `pxyTransaction.txnAmount` | Amount |
| `pxyCustomerInfo.billingLocation.firstName/lastName` | Account holder |

ACH Verify adds `pxyTransaction.processorRefId`, `pxyTransaction.firstMicroDeposit`,
`pxyTransaction.secondMicroDeposit`.

---

## 5. 3D Secure (3DS 1.0 / 2.0)

3DS is a two-step server flow layered on top of AUTH, using `pxyThreeDSecAuth.*` params.

**Flow:**

1. The iFrame returns 3DS context in `threeDSValuesObj` (via `hpciSiteSuccessHandlerV7`+):
   `threeDSOrderId`, `cruiseSessionId`, `cruiseBinStatus`. Carry these to your server.
2. **`verifyenroll`** — server calls the API with `pxyThreeDSecAuth.actionName=verifyenroll`,
   `pxyThreeDSecAuth.authSessionId=[cruiseSessionId]`, `pxyThreeDSecAuth.authOrderId=[threeDSOrderId]`,
   `pxyThreeDSecAuth.callMode=reportall`, plus normal AUTH params.
3. **Challenge detection** — if the response contains `pxyResponse.threeDSAcsUrl` **and**
   `pxyResponse.processorType=3dsecResponse`, a challenge is required: redirect the customer to
   the ACS URL (with the `threeDSPARequest`) and collect the OTP/challenge result. The linking id
   is `pxyResponse.threeDSTransactionId`. If **frictionless** (no `threeDSAcsUrl`), skip to done.
4. **`verifyresp`** — server calls with `pxyThreeDSecAuth.actionName=verifyresp`,
   `pxyThreeDSecAuth.authTxnId=[threeDSTransactionId]`, `pxyThreeDSecAuth.authSessionId` (same as
   verifyenroll), and (3DS 1.0) `authCAVV`/`authECI`. A `status=success` / `responseStatus=approved`
   completes the authorization.

**Key params:**

| Parameter | Value |
|---|---|
| `pxyThreeDSecAuth.actionName` | `verifyenroll` then `verifyresp` |
| `pxyThreeDSecAuth.txnPayName` (`pxyTransaction.txnPayName`) | 3DS payment profile name |
| `pxyThreeDSecAuth.authSessionId` | `cruiseSessionId` from the iFrame |
| `pxyThreeDSecAuth.authOrderId` | `threeDSOrderId` from the iFrame |
| `pxyThreeDSecAuth.authTxnId` | `threeDSTransactionId` from verifyenroll |
| `pxyThreeDSecAuth.callMode` | `reportall` |

Full request/response NVP samples (Cardinal Commerce, 3DS 1.0 & 2.0) are documented at
https://www.hostedpci.com/cardinal-commerce-3ds

---

## 6. Error handling

- **iFrame:** implement `hpciSiteErrorHandler(errorCode, errorMsg)` to surface tokenization
  failures.
- **API:** every response includes `status`. On `status=error`, read `errId`, `errParamName`,
  `errParamValue`. On success, branch on `pxyResponse.responseStatus` (`approved` / `declined` /
  `3dsecure`). See the Common Error Codes section of the documentation for the full list.

---

## 7. Integration checklist

1. Get from HPCI: `sid` (staging + live), `location`, iFrame host, API host, `userName`,
   `userPassKey`, payment profile name.
2. Add the 3 iFrame scripts (with current SRI hashes) + the `<iframe>` + hidden token fields.
3. Set the global `hpciCCFrameHost` / `hpciCCFrameName` / `hpciCCFrameFullUrl`.
4. Implement `hpciSiteSuccessHandler*` (copy tokens → hidden fields → submit) and
   `hpciSiteErrorHandler`.
5. Server-side: POST the tokens to the Payment API (AUTH → CAPTURE, or SALE).
6. (Optional) Add 3DS (`verifyenroll` → challenge → `verifyresp`) and/or ACH (`dataType=achus1`
   iFrame → `paymentACH.action`).
7. Keep the SRI hashes updated when HPCI rotates the scripts (~quarterly).

**Support:** sales@hostedpci.com · +1 (866) 850-3608 · full docs: https://www.hostedpci.com/documentation
