Skip to main content
Version: v2

HCP Registration, Gateway & WAF Best Practices

The HealthSafePay Cloud Platform (HCP) is your secure gateway to Convenient Checkout APIs. This guide covers:

  • How to register and authenticate with HCP
  • How the HCP Gateway and Azure WAF protect your integration
  • Best practices to avoid common WAF/API issues

1. HCP Registration & API Authentication​

Convenient Checkout APIs are available through HCP for merchants, partners, and internal users.

Registration Steps​

  1. Visit the HCP site and review onboarding for the Commerce package.
  2. Register your application in HCP and request access to CCG APIs with the required scopes (API Access Levels).
  3. Configure API access: After approval, use your client credentials (ID/secret) for authentication.
  4. Explore the HCP Console to manage clients, keys, and API usage.
  5. Browse the API Catalog for available APIs and docs.
Resource Groups:
  • STAGE: rg-common-checkout-nonprod (non-prod)
  • PROD: rg-common-checkout-prod (production)

2. HCP Gateway & WAF: What to Watch For​

The HCP Gateway uses Azure Web Application Firewall (WAF) to protect your APIs. Some requests may be blocked if they don’t follow best practices.

ScenarioImpactHow to Fix
URLs in POST body not encodedRequest blockedPercent-encode all URLs in POST bodies
GET with Transfer-Encoding headerRequest blockedNever send this header on GET
Missing Accept headerRequest blockedAlways send Accept on GET
Other WAF triggersRequest blockedSee best practices below

3. Common WAF Block Scenarios​

1. URLs in POST Body (Encoding Required)

Example fields:

  • config.privacypolicyurl
  • appearance.font.fontSources.cssSrc
  • appearance.merchantlogo

Remediation: Always percent-encode URLs in POST request bodies.

2. GET Requests with Transfer-Encoding Header

Including this header on GET requests will trigger the WAF and block the request.


Remediation: Never include Transfer-Encoding on GET requests.

3. Missing Accept Header

Azure WAF blocks GET requests that do not include an Accept header. This affects endpoints like:

  • /token/setup-payment-methods
  • /sessions
  • /payments/{payment_id}
  • /customers/{customer_id}/payment-methods
  • /payment-methods/search

Remediation: Always include an Accept header on GET requests.

4. Other Best Practices
  • GET or HEAD requests should not have a body
  • POST requests must have a valid JSON body
  • Avoid SQL characters in request bodies
  • Encode all URLs in request bodies

4. Best Practices for API Security​

  • Store client credentials and API keys securely
  • Rotate secrets regularly
  • Use least-privilege API scopes (see access levels)
  • Monitor API usage and set up alerts for unusual activity

5. Troubleshooting & Support​


βœ… Quick Checklist​

  • Register and onboard in HCP
  • Request correct API scopes
  • Store credentials securely
  • Encode all URLs in POST bodies
  • Never send Transfer-Encoding on GET
  • Always send Accept on GET
  • No body on GET/HEAD
  • POST body is valid JSON
  • No SQL characters in request bodies

For further information about HCP, visit HCP site


6. Updating the HCP API Gateway YAML Spec​

When endpoints are added or changed, the HCP Stargate Gateway YAML must be updated and re-submitted to the HCP Console under API Management.


6.1 Deployed Endpoints​

Not all API endpoints are routed through HCP. Understanding the distinction is important when registering APIs, debugging gateway issues, or adding new endpoints.

HCP Gateway vs Virtual Service​

HCP Stargate GatewayVirtual Service
Who calls itMerchant server / backend integrationsCCG Widget (browser, user-initiated)
Token scopemerchant, merchant-pci, or merchant-wallet-managementuser
Auth enforced byHCP gateway policynginx + internal auth middleware
Registered in HCP ConsoleYes β€” YAML spec must be uploadedNo β€” never submitted to HCP
CORSNot applicableEnforced by nginx for widget origins
WAF protectionAzure WAF via HCPnginx only
Server block in apispecccgStageServer / ccgProdServernginxServer / prodnginxServer
Path prefixNo prefix (e.g. /payments)/v2/ prefix (e.g. /v2/checkout-sessions/...)
info

A new endpoint belongs in the HCP YAML if its servers: block references ccgStageServer or ccgProdServer. If it references nginxServer or prodnginxServer, it is virtual and should not be submitted to HCP.

HCP Stargate Gateway endpoints and nginx virtual service endpoints are listed separately for each API version below.

HCP Gateway Endpoints (v1)​

MethodPathDomainScopeOperation ID
GET/paymentsPaymentsmerchant, usergetPaymentIntentByMerchantId
POST/paymentsPaymentsmerchant, usercreatePaymentIntent
GET/payments/{paymentId}Paymentsmerchant, usergetPaymentIntent
PATCH/payments/{paymentId}/cancelPaymentsmerchantcancelPayment
PATCH/payments/{paymentId}/capturePaymentsmerchantcapturePayment
PATCH/payments/{paymentId}/confirmPaymentsuserconfirmPayment
POST/refundsPaymentsmerchantcreateRefund
GET/refunds/{refund-id}PaymentsmerchantgetRefund
POST/sessionsSessionsmerchantcreateSession
GET/sessions/{session-id}SessionsmerchantgetSession
POST/token/paymentsPayments (Token)merchant-pcicreatePaymentUsingToken
POST/token/setup-payment-methodsCustomers (Token)merchant-pcicreateCustomerAndSetupPaymentMethod
GET/token/setup-payment-methods/{setup-payment-method-id}Customers (Token)merchant-pcigetSetupPaymentMethodByIdPCIFlow
POST/payment-methods/searchCustomersmerchant, merchant-wallet-managementgetPaymentMethodsSearch
GET/payment-methods/{payment-method-id}Customersuser, merchant-wallet-managementgetPaymentMethod
PATCH/payment-methods/{payment-method-id}Customersuser, merchant-wallet-managementupdatePaymentMethod
DELETE/payment-methods/{payment-method-id}Customersuser, merchant-wallet-managementdeletePaymentMethod
GET/customers/{id}/payment-methodsCustomersusergetPaymentMethods-user
GET/customers/{id}/payment-methods/{payment-method-id}CustomersusergetPaymentMethod-user
PATCH/customers/{id}/payment-methods/{payment-method-id}Customersmerchant, userupdatePaymentMethod-user
DELETE/customers/{id}/payment-methods/{payment-method-id}CustomersuserdeletePaymentMethod-user
POST/customers/{id}/setup-payment-methodsCustomersusercreateSetupPaymentMethod
GET/customers/{id}/setup-payment-methods/{setup-payment-method-id}CustomersusergetSetupPaymentMethodById
GET/banks/routing/{routing-number}ACHusergetBankByRotuingNumber

Virtual Service Endpoints β€” v1 (nginx β€” not submitted to HCP)​

MethodPathDomainNotes
POST/checkout-sessionsCheckout SessionsWidget-initiated
GET/checkout-sessions/{sessionId}Checkout SessionsWidget-initiated
PATCH/checkout-sessions/{sessionId}/cancelCheckout SessionsWidget-initiated
POST/checkout-sessions/{sessionId}/child-sessionsCheckout SessionsWidget-initiated
POST/api-ccg/paymentsPaymentsWidget-initiated
GET/api-ccg/payments/{paymentId}PaymentsWidget-initiated
GET/api-ccg/payments/{paymentId}/confirmPaymentsWidget-initiated
POST/api-ccg/customers/{id}/setup-payment-methodsCustomersWidget-initiated
GET/api-ccg/customers/{id}/setup-payment-methods/{setup-payment-method-id}CustomersWidget-initiated
GET/api-ccg/customers/{id}/payment-methodsCustomersWidget-initiated
GET/api-ccg/customers/{id}/payment-methods/{payment-method-id}CustomersWidget-initiated
PATCH/api-ccg/customers/{id}/payment-methods/{payment-method-id}CustomersWidget-initiated
DELETE/api-ccg/customers/{id}/payment-methods/{payment-method-id}CustomersWidget-initiated
GET/api-ccg/customers/banks/routing/{routingNumber}ACHWidget-initiated

HCP Gateway Endpoints (v2)​

MethodPathDomainScopeOperation ID
GET/paymentsPaymentsmerchant, usergetPaymentIntentByMerchantId
POST/paymentsPaymentsmerchant, usercreatePaymentIntent
GET/payments/{paymentId}Paymentsmerchant, usergetPaymentIntent
PATCH/payments/{paymentId}/cancelPaymentsmerchantcancelPayment
PATCH/payments/{paymentId}/capturePaymentsmerchantcapturePayment
PATCH/payments/{paymentId}/confirmPaymentsuserconfirmPayment
POST/refundsPaymentsmerchantcreateRefund
GET/refunds/{refund-id}PaymentsmerchantgetRefund
POST/sessionsSessionsmerchantcreateSession
GET/sessions/{session-id}SessionsmerchantgetSession
POST/token/paymentsPayments (Token)merchant-pcicreatePaymentIntentRequest
POST/token/setup-payment-methodsCustomers (Token)merchant-pcicreateCustomerAndSetupPaymentMethod
GET/token/setup-payment-methods/{setup-payment-method-id}Customers (Token)merchant-pcigetSetupPaymentMethodByIdPCIFlow
POST/payment-methods/searchCustomersmerchant, merchant-wallet-managementgetPaymentMethodsSearch
GET/payment-methods/{payment-method-id}Customersuser, merchant-wallet-managementgetPaymentMethod
PATCH/payment-methods/{payment-method-id}Customersuser, merchant-wallet-managementupdatePaymentMethod
DELETE/payment-methods/{payment-method-id}Customersuser, merchant-wallet-managementdeletePaymentMethod
GET/customers/{id}/payment-methodsCustomersusergetPaymentMethods-user
GET/customers/{id}/payment-methods/{payment-method-id}CustomersusergetPaymentMethod-user
PATCH/customers/{id}/payment-methods/{payment-method-id}Customersmerchant, userupdatePaymentMethod-user
DELETE/customers/{id}/payment-methods/{payment-method-id}CustomersuserdeletePaymentMethod-user
POST/customers/{id}/setup-payment-methodsCustomersusercreateSetupPaymentMethod
GET/customers/{id}/setup-payment-methods/{setup-payment-method-id}CustomersusergetSetupPaymentMethodById
GET/banks/routing/{routing-number}ACHusergetBankByRoutingNumber

Virtual Service Endpoints β€” v2 (nginx β€” not submitted to HCP)​

MethodPathDomainNotes
GET/v2/checkout-sessions/{sessionId}Checkout SessionsWidget-initiated
PATCH/v2/checkout-sessions/{sessionId}Checkout SessionsWidget-initiated
PATCH/v2/checkout-sessions/{sessionId}/cancelCheckout SessionsWidget-initiated
POST/v2/checkout-sessions/{sessionId}/child-sessionsCheckout SessionsWidget-initiated
POST/v2/api-ccg/paymentsPaymentsWidget-initiated
GET/v2/api-ccg/payments/{paymentId}PaymentsWidget-initiated
POST/v2/payments/{paymentId}/capturePaymentsSplit-tender capture β€” planned, not yet implemented

6.2 V1 β†’ V2 Changes Summary​

CategoryChange
New pathNone β€” v2 HCP endpoints are a 1:1 match with v1
Renamed operationPOST /token/payments: createPaymentUsingToken β†’ createPaymentIntentRequest
Renamed operationGET /banks/routing/{routing-number}: fixed typo getBankByRotuingNumber β†’ getBankByRoutingNumber
New response codes401 and 403 now declared on all protected operations
New headerX-Upstream-Env added to all operations
Security scope prefixfinancial/commerce/nonprodcheckout:* (non-prod) / financial/commerce/checkout:* (prod)
Backend hostChanged from api-v1.healthsafepay.com to api-v2.healthsafepay.com per environment
RemovedDummyRequest schema replaced with domain-named schemas (CancelCheckoutSessionRequest, etc.)

6.3 Update Process​

Step 1 β€” Open HCP Console​

Go to https://console.hcp.uhg.com/ β†’ API Management β†’ select the correct Resource Group for the target environment:

EnvironmentResource Group
dev, perf, reg, testrg-common-checkout-nonprod
stagerg-common-checkout-nonprod
prodrg-common-checkout-prod

Step 2 β€” Edit the source YAML​

Source YAMLs and the generation script live in the hcp-api repository:

hcp-api/
dev/ *-dev-v2.yaml # Source YAML (reference)
perf/ *-perf-v2.yaml
reg/ *-reg-v2.yaml
stage/ *-stage-v2.yaml
test/ *-test-v2.yaml
prod/ *-checkout-v2.yaml

The dev source is the reference for paths: and components:. All other environments share the same paths but have their own x-instance: block (backend host, CORS origins). Never overwrite env-specific fields when syncing from dev.

Step 3 β€” Generate the submission file​

From the source YAML (e.g. dev/*-dev-v2.yaml), produce a submission file that contains only the spec: block β€” strip the outer kind:, metadata:, and status: gateway wrapper. The resulting *-updated.yaml must pass all HCP MUST Rules before upload.

Step 4 β€” Apply to the HCP portal​

In the HCP Console, select the API resource for the target environment and upload the *-updated.yaml file. Deploy the new version and verify routing with a smoke test.

Step 5 β€” Propagate to remaining environments​

Repeat Steps 2–4 for each environment. Each env's *-updated.yaml is submitted independently.


6.4 HCP MUST Rules​

The submission file must satisfy all of the following rules before it can be accepted by HCP:

RuleWhat to check
Every POST / PUT / PATCH must have a requestBodyInclude required: false with a domain-named schema even when no body is needed
requestBody.content.application/json.schema must resolveThe $ref must exist in components/schemas
Every operation must have an operationIdcamelCase, matching the Java controller method name
Every operation must have securityAt least one scope (merchant, user, or merchant-pci)
Every operation must declare a 2xx responseAt least one of 200 / 201 / 202
Empty-body PATCH / POST endpoints

If the controller method has no @RequestBody (e.g., cancel by path param only), you must still declare a requestBody with required: false and a domain-named schema. Do not use generic names like DummyRequest.

requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/CancelCheckoutSessionRequest'

# In components/schemas:
CancelCheckoutSessionRequest:
type: object
description: >
No fields required. Session identified by path param and X-Merchant-Id header.
Present to satisfy the HCP PATCH requestBody requirement.
properties: {}

6.5 Per-Environment Reference​

EnvironmentBackend HostCORS OriginResource Group
devdev-api-v2.healthsafepay.comdev-wallet.healthsafepay.comrg-common-checkout-nonprod
perfperf-api-v2.healthsafepay.comperf-wallet.healthsafepay.comrg-common-checkout-nonprod
regreg-api-v2.healthsafepay.comreg-wallet.healthsafepay.comrg-common-checkout-nonprod
stagestg-api-v2.healthsafepay.comstg-wallet.healthsafepay.comrg-common-checkout-nonprod
testtest-api-v2.healthsafepay.comtest-wallet.healthsafepay.comrg-common-checkout-nonprod
prodapi-v2.healthsafepay.comwallet.healthsafepay.comrg-common-checkout-prod