# Request an access token
Source: https://developer.hellgate.io/platform/api-reference/oauth2/request-an-access-token
/platform/openapi.yaml post /oauth2/token
Exchange your client ID and client secret for an OAuth2 access token using the client-credentials grant. Send the credentials with HTTP Basic authentication and the form fields as `application/x-www-form-urlencoded`.
# Overview
Source: https://developer.hellgate.io/platform/api-reference/overview
The Authentication API issues OAuth2 access tokens for Hellgate Cloud Platform services.
The Authentication API issues the **OAuth2 access tokens** used to call Hellgate Cloud Platform services. You
exchange a **client ID** and **client secret** for a token using the **client-credentials** grant, then send
the token as a bearer token on each request.
The platform-level OAuth2 API. Duplicate the **Dedicated instance —
template** environment and fill in your client credentials. **OAuth2 → Request an access token** is the
token endpoint documented here, sent as a real request; the product collections in this workspace get
their tokens the same way, from a pre-configured Authorization tab.
## Token endpoint
The token endpoint is hosted at `https://auth.eu1.hellgate.cloud`.
## Authentication
Send your client ID and client secret to the token endpoint using **HTTP Basic** authentication. The
**Request an access token** operation describes the request and response in full.
Tokens are scoped to an **audience** — the service instance they may call — and carry the **scopes** that gate
individual endpoints. The `audience` and `scope` parameters are both required on every token request; there
are no defaults, and each must fall within the limits provisioned on your client. For how a specific product
validates the token and which scopes and audience it requires, see that product's access guide — for example,
[Specter Authentication](/products/specter/authentication).
## Data Classification
Fields that carry regulated data are marked with a classification pill next to the parameter name in this
reference. The marker tells you what kind of data the field holds, so you can see at a glance which parts of a
payload attract handling obligations before you write any code against them.
| Marker | The field carries |
| - | - |
| pci-pan | The primary account number — a card number, or a value from which one can be reconstructed. |
| pci-sad | Sensitive authentication data — security codes and the equivalent authentication values issued for a token. |
| pii | Personal data under the GDPR — any information relating to an identified or identifiable person, not only the cardholder. |
Most fields carry no marker at all. The absence of one is a statement that the field holds none of the
categories above — not that the field has yet to be reviewed. Masked and truncated card numbers are the
common example: `411111 •••••• 1111` identifies nobody on its own, so it carries no marker.
The marker is also a gate, not just a label. Sending values into `pci-pan` or `pci-sad` fields requires your
PCI DSS certification on file at **SAQ-D** or a full Report on Compliance (RoC). Sending
[personal data](https://eur-lex.europa.eu/eli/reg/2016/679/oj) into `pii` fields requires a data processing
agreement (DPA) between us. Contact [support@hellgate.io](mailto:support@hellgate.io) to put either in place
or to learn more.
The same markers are used on the other Hellgate Cloud Platform references that carry them, so a marker means
the same thing wherever you meet it.
# Authentication
Source: https://developer.hellgate.io/platform/authentication
Hellgate Cloud Platform services authenticate with API keys, OAuth2 bearer tokens, or mTLS. This page covers OAuth2 access tokens.
Hellgate® Cloud Platform services authenticate with one of three mechanisms — **API keys**, **OAuth2 access
tokens** (bearer JWTs), or **mTLS**. OAuth2 access tokens are the standard mechanism for the services running
on dedicated infrastructure; Commerce authenticates with an API key.
| Product | API key | OAuth2 | mTLS |
| - | - | - | - |
| [Guardian](/products/guardian/overview) | ✓ deprecated | ✓ | — |
| [Specter](/products/specter/overview) | — | ✓ | — |
| [Link](/products/link/overview) | — | ✓ | — |
| [Commerce v1](/products/commerce/v1/overview) | ✓ | — | ✓ |
| [Commerce v2](/products/commerce/v2/overview) | ✓ | — | — |
## OAuth2 access
OAuth2 access is a platform-level capability shared by every service that supports it. This page covers OAuth2
access tokens only — for API keys and mTLS, see the relevant product's documentation.
### Obtain client credentials
Client credentials are issued by Hellgate. Contact Hellgate support to request them. Each credential is scoped
to a specific service (its **audience**) and is provisioned with a defined set of **maximum scopes** based on
your request. A token can never exceed the audience and scopes provisioned on the credential it is issued from.
### Request a token
Exchange your client credentials for an access token at the OAuth2 token endpoint:
```
https://auth.eu1.hellgate.cloud/oauth2/token
```
You authenticate to this endpoint with HTTP Basic authentication, sending your client ID and client secret.
See the [Authentication API](/platform/api-reference/overview) reference for the full request and response.
### Audiences
A token names one or more **audiences** — the service instances it is allowed to call, carried in the token's
`aud` claim. A service rejects any token whose audience does not name it, so a token issued for one instance
cannot be used against another.
Pass audiences in the `audience` request-body parameter as a space-delimited list. There is no default
audience: the parameter is required on every token request, and each value must be within the audiences
provisioned on your credential. A request without a valid audience is rejected. To target more than one service
with a single token, list each audience (see [Composition](#composition)).
### Scopes
You must request **scopes** through the `scope` parameter on every token request, as a space-delimited list.
The requested scopes must be a subset of the maximum scopes provisioned on your credential — there are no
default scopes. The available scopes depend on the service; see, for example,
[Specter scopes](/products/specter/authentication#scopes).
### Composition
When a token is used transitively across composed services — for example, Specter composing with Link — it
must name every service in the composition and carry the scopes each one requires. List all the audiences — each
the **instance name** of a service — together with the union of their scopes when you obtain the token (for
example, `audience=my-specter-instance my-link-instance`).
### Use the token
Send the access token in the `Authorization` header on every API request:
```http theme={null}
Authorization: Bearer
```
The token carries the scopes that gate access to individual endpoints and expires 30 minutes after it is
issued (`expires_in` is `1800`). Cache and reuse it until shortly before it expires, then request a new token
on expiry or on a `401` response.
# Cloud Platform Updates
Source: https://developer.hellgate.io/platform/changelog
New releases and improvements of the Cloud Platform.
## Data Classification Markers in the API References
Fields that carry regulated data now show a classification marker next to the
parameter name throughout the API references. `pci-pan` marks a card number, or
a value from which one can be reconstructed; `pci-sad` marks sensitive
authentication data such as security codes and cryptograms; `pii` marks personal
data under the GDPR. You can see which parts of a payload attract handling
obligations before writing any code against them.
Most fields carry no marker, and that absence is deliberate: it states the field
holds none of those categories, not that nobody has looked yet. Masked and
truncated card numbers are the common case — `411111 •••••• 1111` identifies
nobody on its own, so it carries no marker.
The marker is also a gate. Sending values into `pci-pan` or `pci-sad` fields
requires your PCI DSS certification on file at SAQ-D or a full Report on
Compliance; sending personal data into `pii` fields requires a data processing
agreement. Contact [support@hellgate.io](mailto:support@hellgate.io) to put
either in place.
The full legend is on the
[Authentication API overview](/platform/api-reference/overview#data-classification).
Nothing about any endpoint changed — this is documentation only.
## Hellgate Web SDK (v3.11.0)
### Central Control Over Card Saving
Decide once, when you create a session, whether cards are saved — always,
never, or left to the cardholder — and the SDK enforces that policy at
checkout. Your card-retention rules stay consistent across every page that
embeds the SDK, with nothing extra to implement in each frontend. The SDK
also tells you which policy is active, so you can show a "Save my card"
checkbox only when the cardholder really has the choice.
### Improvements and bugfixes
* A cardholder's decision not to save their card is now always honored.
Previously, in some integrations, declining to save a card could still
result in a saved card.
## Link documentation now public
[Link](/products/link/overview) — the protocol-abstraction runtime of the
Composable Payment Architecture — now has public documentation. Link is the
platform's PSP and provider connectivity layer: define a versioned API
contract (a **protocol**) once and bind it to any provider through
declarative **backends**, so integration becomes configuration, not code. It
is the component [Commerce](/products/commerce/v2/overview) routes through to
reach acquirers and PSPs, and that [Specter](/products/specter/overview)
reaches through to call external risk engines.
Explore the [overview](/products/link/overview),
[core concepts](/products/link/concepts/protocols), and the
[API reference](/products/link/api-reference/getting-started).
## Hellgate Web SDK (v3.10.0)
### Cardholder-Aware Token Lifecycles
Align token retention with what your cardholder actually agreed to. A new optional
`ephemeral?: boolean` argument on `process()` and `tokenize()` defaults to `true`,
meaning the cardholder is *not* remembered. Flip it to `false` only on explicit
consent — for example, when a customer ticks a "Save my card" box at checkout.
### Smarter Scheme Validation
Allowed card schemes configured on the session now flow through to client-side
card number validation. Cardholders see scheme errors immediately, before the
request ever leaves the browser.
### Improvements and bugfixes
* Empty `card_schemes` configuration now correctly allows all schemes.
* Separate expiry month/year inputs now treat `'1'` as a valid month and
properly reject past-expiry dates.
* Demo: a new "Save my card" checkbox in the tokenization demo wires straight
into the new ephemeral toggle so you can try it end-to-end.
## Hellgate Web SDK (v3.9.1)
Security improvements.
## Hellgate Web SDK (v3.9.0)
Added support to split the expiriy input fields in the Web SDK.
## Hellgate Web SDK (v3.8.1)
September cleanup and maintenance release for our SDKs.
## Hellgate Web SDK (v3.8.0)
Validate CVC length based on card scheme in multi-line forms.
## Hellgate Android SDK (v1.1.0)
The Android SDK now encrypts the full payload — including any additional data —
into a single JWE and returns it to your app, instead of calling the tokenization
backend directly. This simplifies your integration and keeps sensitive data
encrypted end to end.
### Improvements and bugfixes
* Additional cardholder data is now encrypted as part of the JWE token.
* Hellgate error responses now surface with clearer, more actionable detail.
* Removed support for tokenizing through an external token provider.
* Updated environment URLs.
## Hellgate Web SDK (v3.7.0)
Add 'onSessionComplete' handler to Hellgate® client with result data.
## Hellgate Web SDK (v3.5.3)
Improved the SDK with small but important fixes:
* Fix masked input behaviour
* Reject cardHandler.process() promise if BE responds 40x / 50x status code
* Await cardHandler.process() throws exceptions if card date is not complete or invalid
* Show full CVC code up to 4 digits
* Card scheme validation by default
* UnionPay card number input
Added some new features:
* Encrypt additional\_data payload on tokenize
* User can refresh CVC2 code of a token from WebSDK
## Hellgate iOS SDK (v1.0.0)
The first release of the Hellgate® iOS SDK brings cardholder data tokenization
to native iOS apps. Collect and tokenize the card number, CVC, and expiration
date, and attach additional fields to capture cardholder information — so raw
card data never touches your own backend.
## Hellgate Android SDK (v1.0.0)
The first release of the Hellgate® Android SDK brings cardholder data
tokenization to native Android apps.
# Compose vs. Composed
Source: https://developer.hellgate.io/platform/composition
The Hellgate Cloud Platform offers individual composable services and as well as the ready to go composed version of it - Commerce.
The Hellgate Cloud Platform follows two distinct usage patterns: **composing services yourself** or **using Commerce**, which is already composed for you.
## Composable Services
The platform's individual services each do one thing well and are designed to slot into any payment stack. You pick the ones you need and compose them yourself.
PCI-compliant tokenization vault. Stores card data, manages PCI tokens, network tokens, and generic tokens. The compliance layer underneath any payment stack.
Real-time fraud intelligence. Scores every transaction as it passes through your payment flow.
PSP abstraction layer. One integration, access to acquirers and payment service providers globally.
Coming Soon
Orchestration fabric. Routes payment flows between acquirers, PSPs, and fraud tools with intelligent routing and automatic retries.
Each service is standalone and built for composability.
## Commerce: The Composed Product
Commerce is a complete and opinionated payment orchestration service built by composing our platform's own services. It provides ready-made implementations of the capabilities most payment businesses need:
* **Payments** — CIT, MIT, and the payment lifecycle management
* **Authentications** — 3-D Secure and FIDO (Passkeys)
* **Ecosystem enablement** — marketplace and partner network operating models
Under the hood, Commerce routes through Hub to Guardian (tokenization), Link (PSP connectivity), and Specter (fraud intelligence) — the same services that will be made available to you as standalone components.
This means Commerce is not a walled garden. It is a production-proven composition of the same building blocks you have access to. If you ever want to build your own stack, the components are already there.
## Progressive Enhancement: BYOG
Even when using Commerce, you can still exercise composability.
By default, Hellgate manages a Guardian instance for sensitive data stored in your Commerce account.
If you already operate a Guardian instance yourself, you can connect it instead.
This is called **Bring Your Own Guardian (BYOG)**. Commerce continues to handle payments, authentications, and ecosystem operations — the Guardian component is simply replaced with yours.
BYOG lets you:
* **Reuse existing tokens** — tokens are accessible in both services
* **Control the token store** — card data stays in the Guardian instance you own
* **Bridge both patterns** — operate Guardian standalone and Commerce against the same underlying data
BYOG is configured at the Commerce account level. Contact our support to set it up.
## Choosing Your Approach
Choose individual services when you want to build custom payment orchestration and need specific components — a compliance layer, a fraud engine, a PSP connector — without adopting a pre-built product.
Start with **Guardian** for PCI tokenization, the most commonly needed component. Additional services are releasing progressively.
Choose **Commerce** when you want a production-ready payment orchestration service — payments, authentications, ecosystem support — without building each layer yourself.
**Commerce** is a faster path to a complete payment stack. It is built from the same platform services, so you are not locked in.
# The CPA
Source: https://developer.hellgate.io/platform/cpa
Introduction to the Composable Payment Architecture (CPA)
The **Composable Payment Architecture (CPA)** is a term we coined recently. It describes how we built our payment systems and how we think you should build yours too. Instead of locking everything into one big system, CPA breaks things into smaller pieces you can mix and match however you need.
## What is CPA?
CPA isn't a product or service, it's a way of thinking about payment systems. The idea is simple: build systems from independent pieces that work together, rather than one big monolithic thing.
You compose services together instead of bundling everything into a single component. Each piece does one thing well, and you can swap them out or rearrange them as your needs change.
### How CPA Differs from Walled Gardens
Most payment platforms are walled gardens. You get their way of doing things, bundled services you might not need, and switching costs that keep you locked in.
CPA flips this around. You pick the services you actually need. You can mix services from different providers. You control your payment flows instead of adapting to someone else's constraints. When you need to change something, you swap out a component instead of rebuilding everything.
## Why CPA Matters
Payment systems are messy. Everyone builds their own orchestration layers, optimized for their specific needs. Integration is painful. Scaling is hard. Changing anything requires rebuilding large parts of the system.
Walled garden platforms make this worse. They lock you into their way of doing things. You adapt to them, not the other way around.
CPA fixes this by letting you build from independent pieces. Change one component without touching the rest. Swap providers when you need to. Keep control of your architecture instead of being forced into someone else's mold.
## Core Principles
CPA follows five simple principles:
### Separation of Concerns
Keep different domains separate. Risk, settlement, data—each has its own boundaries. Change one without breaking the others.
### Composability
Everything is replaceable. Swap components, rearrange them, extend them. No need to rebuild the whole system.
### Openness
Use open APIs and contracts, not proprietary formats. Mix services from different providers.
### Programmability
Everything is API-driven. Automate what you can. Extend what you need.
### Evolvability
Change is constant. CPA lets you evolve incrementally—add a new PSP, update compliance rules, adopt new tech—without big rewrites.
## Composition Over Aggregation
CPA prefers composition over aggregation.
**Composition** means combining independent services. Each service stays separate—you can swap them out or rearrange them.
**Aggregation** bundles multiple functions into one component. It seems easier at first, but you end up with tight coupling, less flexibility, and harder changes.
### Example: Fraud Checks in Authorization Flows
Say you have a payment gateway that bundles fraud checks into authorization. Every authorization triggers a fraud check. To change this, you need to add flags and modify the authorization logic. Now authorization and fraud are tightly coupled—hard to test, hard to change, hard to swap providers.
With CPA, authorization and fraud are separate services. You compose them however you need:
* `fraud >=> auth` → check fraud first, then authorize
* `auth >=> fraud` → authorize first, then check fraud
Each service stays independent. You control how they work together.
## How We Build Hellgate with CPA
CPA isn't just theory—it's how we build the Hellgate Cloud Platform. Every service follows CPA principles. They work together, but you can use them independently.
We learned this from building payment systems and consulting in the payments world. We saw the problems: walled gardens, legacy systems, fragile protocols, systems that don't connect well. CPA is our answer.
### Our Platform Journey
We're building Hellgate Cloud Platform as a collection of composable services. Commerce V2 is our CPA-based implementation—it's built entirely using CPA principles, composing independent services together to create flexible payment orchestration.
One of those composable services is **Guardian**—our PCI-compliant tokenization service. Guardian is used within Commerce V2, but it's also available as a standalone service you can use independently or compose with your own services.
More services are rolling out soon for general access: **Hub** and **Pulse**. Together with Guardian, Link, Specter, and Commerce V2, these make up our complete product stack. Each one is:
* **Standalone** — Works on its own
* **Composable** — Works with other services, ours or third-party
* **CPA-aligned** — Built with composable architecture from the start
Take what you need, when you need it. No forced bundles, no monolithic platform.
## Building with CPA
When building payment software with CPA:
1. **Think in flows** — Break processes into steps you can rearrange
2. **Design for swapping** — Make components replaceable
3. **Focus on interfaces** — Define how components talk to each other, not how they work inside
4. **Plan for change** — Structure things so you can evolve incrementally
5. **Compose, don't bundle** — Keep services independent
This approach makes systems easier to maintain, scale, and adapt as your needs change.
## Learn More
See CPA in action:
* [Commerce V2](/products/commerce/v2/overview) — A CPA-based implementation that orchestrates payment flows by composing services
* [Guardian](/products/guardian/overview) — One of the composable services used in Commerce V2, also available standalone
* [Link](/products/link/overview) — The protocol-abstraction runtime that decouples callers from providers, letting Commerce V2 and Specter reach PSPs and external risk engines
* [Specter](/products/specter/overview) — The decisioning service for fraud detection and prevention, composable and extensible through Link
CPA is our vision for payment architecture: systems that evolve, integrate, and adapt instead of locking you in.
# Hellgate® Cloud Platform
Source: https://developer.hellgate.io/platform/index
Overview of the next generation payment platform
The Hellgate Cloud Platform is a comprehensive payment infrastructure that provides secure, scalable,
and flexible solutions for modern payment processing. It is the implementation of what we defined to be the **[Composable Payment Architecture](/platform/cpa)**.
Built with composability and compliance at its core, the platform enables you to build sophisticated payment experiences while maintaining the highest security standards.
## Infrastructure & Deployment
Hellgate Cloud Platform services are designed with enterprise-grade infrastructure in mind.
### Flexible Deployment Options
Hellgate Cloud Platform services run on **dedicated, single-tenant infrastructure** hosted on Microsoft Azure across multiple regions. You choose a region close to your business workloads—reducing transaction latency, satisfying data residency requirements, and keeping your payment infrastructure where your operations are.
For a full list of available locations, see the [Azure global infrastructure overview](https://azure.microsoft.com/en-us/explore/global-infrastructure/geographies/).
**Always dedicated, always yours**
Every Hellgate service is provisioned exclusively for your organisation. There are no noisy neighbours: compute, storage, and network resources are never shared with other clients. Your payment data is physically isolated at the infrastructure level, with no possibility of cross-tenant access. We operate and manage the infrastructure on your behalf, but full data ownership stays with you.
**Commerce V2: shared infrastructure also available**
Commerce V2 is the one exception to the dedicated-only model. Alongside dedicated deployments, we also operate a **shared Commerce V2 service**—available for both Test and Production tiers.
This means you can run production payment workloads on our shared Commerce V2 infrastructure, not just test environments. The shared service is fully managed, fast to onboard, and a cost-effective starting point when complete infrastructure isolation is not a hard requirement.
| | Shared | Dedicated |
| - | - | - |
| Tenancy | Multi-tenant | Single-tenant |
| Data isolation | Logical | Physical |
| Onboarding | Immediate | Requires provisioning |
| Tiers | Test + Production | Test + Production |
| Sizing | Shared resources | Exclusive reservations |
If data sovereignty, regulatory compliance, or strict performance SLAs are a requirement for you, choose a dedicated Commerce V2 deployment.
## Platform Products
The Hellgate Cloud Platform currently consists of two main products, with more services rolling out soon:
A unified payment processing API for handling payments, tokens, authentications, and mobile wallets. Commerce V2 provides a programmable platform-as-a-service designed around four main domains: Payments, Tokens, Authentications, and Mobile Wallets.
A fully PCI-compliant tokenization service delivered as managed dedicated infrastructure. Guardian provides a protective layer between your services and sensitive payment data, enabling composability without compliance concerns.
Real-time fraud intelligence layer that analyzes every transaction as it moves through your payment flow, assigning risk scores and automatically blocking bad actors before they reach checkout.
Unified PSP abstraction layer that gives you instant access to acquirers, PSPs, and services through a single interface, so you can scale globally without touching another integration.
Coming Soon
Orchestration fabric that connects your entire payment stack. Hub links acquirers, PSPs, and fraud prevention tools into one coordinated system with intelligent routing and automatic retries.
Coming Soon
Real-time observability and metrics layer that transforms raw transaction data into live insights, streaming events and surfacing performance trends across every flow.
## Why Hellgate Cloud Platform?
The platform is designed to solve the common challenges in payment processing:
* **Compliance by Design**: Built-in PCI DSS compliance ensures sensitive data never touches your systems
* **[Composable Architecture](/platform/cpa)**: Products work together seamlessly or independently, giving you full control
* **Unified APIs**: Consistent interfaces across all products reduce integration complexity
* **Proximity Advantage**: Multi-region cloud infrastructure enables deployment close to your users for top-notch latency and performance
* **Data Privacy**: Dedicated infrastructure ensures complete data isolation—your payment data stays yours, with no shared resources or cross-tenant access
* **Enterprise Ready**: Dedicated infrastructure deployments with managed resources for your business
* **Developer Friendly**: Comprehensive documentation, SDKs, and clear integration patterns
# Overview
Source: https://developer.hellgate.io/platform/network-tokens
Network tokens replace card PANs with scheme-issued tokens for improved security and authorization rates. Supported across Guardian and Commerce.
Network tokens are payment credentials issued directly by card schemes — Visa, Mastercard, American Express — as replacements for the actual card number (PAN). Instead of the raw PAN, transactions use a scheme-issued **Token PAN (TPAN)** scoped to a specific card and merchant context.
Both [Guardian](/products/guardian/tokens/network-tokens) and [Commerce](/products/commerce/v2/tokens/network) support network tokens. Lifecycle management — including updates when cards expire or are re-issued — is handled automatically by the platform.
Hellgate is a certified **Token Service Provider (TSP)** with the card schemes. As part of enabling network tokens, we register and onboard your business with the schemes on your behalf — so you receive scheme-issued tokens without holding your own token requestor certification or managing scheme enrollment yourself.
**Benefits**
* **Higher authorization rates** — scheme-recognized tokens are treated as lower-risk and authorize at higher rates than raw PANs
* **Reduced fraud** — tokens are scoped to a specific merchant and cannot be reused outside that context
* **Lower interchange fees** — some schemes offer preferential rates for network token transactions
* **PSP portability** — a single network token can be used with multiple PSPs
* **Fully managed onboarding** — as a certified TSP, Hellgate handles scheme registration and merchant onboarding for you
## Flows
These flows show how a network token is created and used across a card's lifecycle, with Hellgate shown as a single actor. The exact API calls depend on the product — see [Guardian and Commerce](#guardian-and-commerce) for how each one provisions network tokens.
### Create a Network Token
When you tokenize a card, Hellgate requests a network token from the card scheme. The scheme provisions a TPAN bound to the card and your merchant, which Hellgate associates with the token.
```mermaid theme={null}
sequenceDiagram
autonumber
participant M as Merchant
participant H as Hellgate
participant S as Card Scheme
M->>+H: Tokenize card
H->>+S: Provision network token
S->>-H: Token PAN (TPAN)
H->>-M: Token (enriched with network token)
```
### Store Credentials at Checkout
When a merchant wants to store a card on file, the first authorization can run on the raw card number (FPAN) and the network token is provisioned only after that authorization succeeds. Provisioning a network token calls out to the card scheme and can add noticeable latency, so it should not be wired directly into the checkout path — authorize on the FPAN first to keep checkout fast, then provision the network token out of band once the payment is approved.
```mermaid theme={null}
sequenceDiagram
autonumber
participant M as Merchant
participant H as Hellgate
participant P as PSP
participant S as Card Scheme
M->>+H: Tokenize card
H->>-M: Token (FPAN)
M->>+P: Authorize first payment with FPAN
P->>-M: Authorization approved
Note over M,S: Provision off the checkout path
M->>+H: Provision network token from the stored card
H->>+S: Provision network token
S->>-H: Token PAN (TPAN)
H->>-M: Network token ready for future payments
```
### Customer Initiated Transaction (CIT)
When a cardholder is present at checkout, a cryptogram must be requested before authorization. The cryptogram is a one-time proof of token ownership that your PSP uses to validate the transaction.
```mermaid theme={null}
sequenceDiagram
autonumber
participant C as Customer
participant M as Merchant
participant H as Hellgate
participant S as Card Scheme
participant P as PSP
C->>M: Initiate payment
M->>+H: Request payment data
H->>+S: Generate cryptogram
S->>-H: Cryptogram
H->>-M: TPAN + Cryptogram
M->>+P: Authorize with TPAN + Cryptogram
P->>-M: Authorization result
M->>C: Payment confirmed
```
### Merchant Initiated Transaction (MIT)
For recurring charges where the cardholder is not present — subscriptions, installments, deferred billing — the scheme manages the TPAN lifecycle automatically. Most processors do not require a new cryptogram for MIT, simplifying the authorization flow.
```mermaid theme={null}
sequenceDiagram
autonumber
participant M as Merchant
participant H as Hellgate
participant P as PSP
M->>+H: Retrieve token
H->>-M: Current TPAN
M->>+P: Authorize with TPAN
P->>-M: Authorization result
```
MIT cryptogram requirements vary by processor. Check your PSP's documentation for their specific requirements for recurring network token transactions.
## Supported Schemes
* Visa
* Mastercard
* American Express
* Discover *(coming soon)*
* Diners Club *(coming soon)*
## Guardian and Commerce
Both products support network tokens, but handle the relationship to PCI tokens differently:
| | Guardian | Commerce |
| - | - | - |
| Provisioning | Explicit — provisioned separately from PCI tokens | Automatic — provisioned when you create a Commerce token (if enabled for your account) |
| Token lifecycle | Independent — PCI token and network token lifecycles are separate | Unified — network token lifecycle is aligned with the Commerce token |
Provisioning sources, cryptogram types, and API usage.
Automatic provisioning, cryptogram request workflow, and PSP integration.
## Get Started
Enable network tokens for testing and production. Add-on feature — requires activation.
Test provisioning and cryptogram generation with the built-in Network Token Sandbox.
# Setup
Source: https://developer.hellgate.io/platform/network-tokens-setup
Network tokens are an add-on feature on all Hellgate products. Learn how to enable them for testing and production.
Network tokens are an add-on feature available on both Guardian and Commerce. They are not enabled by default and require activation through Hellgate support.
## Testing
On the Test tier, Hellgate provides a built-in **Network Token Sandbox** that simulates card scheme responses without forwarding requests to real networks. Once network tokens are activated for your test account, the sandbox is available immediately — no additional configuration required.
Learn about standard and deterministic testing modes, and how to test the full network token lifecycle.
## Production Activation
To enable network tokens in production, contact your account representative or reach out to Hellgate support. Provide the following information:
### Business Details
| Field | Notes |
| - | - |
| Legal Name | Must match official registration records |
| Company Name (trade) | Trading or brand name if different from legal name |
| Address | City and country of registered business |
| Website | Primary domain |
| Primary Contact | First name, last name, and email address |
| VAT Code | Tax registration number, if applicable |
| MCC | Four-digit Merchant Category Code classifying your primary business activity |
### Acquirer Details
If you do not have a direct acquirer relationship, these values can be obtained from your PSP.
| Field | Notes |
| - | - |
| `acquirerIca` | Acquirer Interbank Card Association (ICA) number |
| `acquirerMerchantId` | Merchant ID assigned by your acquirer |
| `acquirerBIN` | Acquirer Bank Identification Number |
### Optional Fields
| Field | Notes |
| - | - |
| `programName` | Cardholder-facing merchant name (e.g. `"myShoppay"`). Required for Secure Card on File (SECURE\_COF) programs. |
## What Happens Next
After receiving your details, Hellgate configures your account and confirms once network tokens are active. No code changes are required — token provisioning and lifecycle management work automatically once the feature is enabled.
# Android SDK
Source: https://developer.hellgate.io/platform/resources/sdks/android-sdk
The Android SDK enables you to capture credit card data, additional personal data, and process them to create a Hellgate® Token. This token can then be used to process payments with the Hellgate® API.
The SDK is written in Kotlin and is available as an Android dependency. It aims to provide a set of UI components and helpers that can be used to collect payment method data from the user with ease.
## Installation
The SDK is available on [Maven Central](https://central.sonatype.com/artifact/io.hellgate/android-sdk). To install the SDK, add the following lines to your `build.gradle.kts` or respective `settings.gradle.kts` file.
```kotlin theme={null}
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
```
Then add the following to your `build.gradle.kts` file:
```kotlin theme={null}
dependencies {
implementation("io.hellgate:android-sdk:")
}
```
## Usage
### Initialization of the UI Components
The SDK provides a set of UI components that can be used to collect payment method data from the user. These could look similar to the following image, depending on the design of your application.
The form in the picture is composed of the following separate fields:
* `CardNumberField` - A class that collects card details from the user.
* `ExpiryDateField` - A class that collects the expiry date of the card from the user.
* `CvcNumberField` - A class that collects the CVC of the card from the user.
These classes are intended to be set up in a viewModel while the `ComposeUI` function of the class should be called in your compose UI code to actually draw the fields as part of your user interface. With the `onValueChange` callback, you can listen to changes in the field state and update your viewModel accordingly.
```kotlin theme={null}
@Composable
fun ComposeUI(
onValueChange: (FieldState) -> Unit,
modifier: Modifier = Modifier,
onFocused: () -> Unit = {},
onBlur: () -> Unit = {},
colors: TextFieldColors = TextFieldDefaults.colors(errorTextColor = MaterialTheme.colorScheme.error),
shape: Shape = OutlinedTextFieldDefaults.shape
)
```
#### FieldState
The field state is a data class that holds the state of the field. It contains the following properties and will be updated as the user interacts with the field:
```kotlin theme={null}
data class FieldState(
val valid: Boolean = false,
val empty: Boolean = true,
val error: List = listOf(FieldError(FieldError.ErrorType.BLANK))
)
data class FieldError(
val errorType: ErrorType,
) {
enum class ErrorType {
INVALID,
INCOMPLETE,
BLANK
}
}
```
#### Styling
The `ComposeUI` function allows you to pass in an `androidx.compose.material3.TextFieldColors` object to style the field and overwrite default colors. If not overridden, the default colors will be used, with the `MaterialTheme.colorScheme.error` color being used for the error state. The `shape` parameter allows you to pass in a `androidx.compose.ui.graphics.Shape` object to style the field and overwrite the default shape. If not overridden, the `OutlinedTextFieldDefautls.shape` will be used.
### CardNumberField
The `CardNumberField` class is used to collect the card number from the user. It can be initialized with a label that will be displayed on/above the input field. The following pictures give examples of how the field could look empty / filled and with a Luhn-invalid number.
#### Code sample
```kotlin theme={null}
class MyViewModel : ViewModel() {
val cardNumberField = CardNumberField("Custom Card Number Label")
val cardNumberState = MutableStateFlow(FieldState())
// ...
}
class MyScreen : ComponentActivity() {
val viewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Column {
CardNumberField()
}
}
}
@Composable
fun CardNumberField() {
viewModel.cardNumberField.ComposeUI(
onValueChange = { viewModel.cardNumberState.value = it },
modifier = Modifier.fillMaxWidth(),
onFocused = { /* handle focus */ },
onBlur = { /* handle blur */ }
// shape = RoundedCornerShape(10.dp)
// colors = TextFieldDefaults.colors(errorTextColor = Color.Red)
)
}
}
```
### ExpiryDateField
The `ExpiryDateField` class is used to collect the expiry date of the card from the user. The following pictures give examples of how the field could look empty / filled and with an invalid date.
#### Code sample
```kotlin theme={null}
class MyViewModel : ViewModel() {
val expiryDataField = ExpiryDateField("Custom Expiry Label")
val expiryDateState = MutableStateFlow(FieldState())
// ...
}
class MyScreen : ComponentActivity() {
val viewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Column {
ExpiryDateField()
}
}
}
@Composable
fun ExpiryDateField() {
viewModel.expiryDataField.ComposeUI(
onValueChange = { viewModel.expiryDateState.value = it },
modifier = Modifier.fillMaxWidth(),
onFocused = { /* handle focus */ },
onBlur = { /* handle blur */ }
)
}
}
```
### CvcNumberField
The `CvcNumberField` class is used to collect the CVC of the card from the user. The following pictures give examples of how the field could look empty / filled and with an invalid CVC.
#### Code sample
In case you would like to use the `CvcNumberField` to also accept CVV (4-digit codes), you will need to pass in the maximum length of the CVC/CVV as a flow according to the card brand you are expecting. This flow can be retrieved from the `CardNumberField` class, which will try to imply the brand of the card based on the card number. If no flow is provided, the default maximum length of 3 digits will be used.
```kotlin theme={null}
class MyViewModel : ViewModel() {
val cardNumberField = CardNumberField("Custom Card Number Label")
val cvcField = CvcNumberField(cardNumberField.maxBrandCvcLength)
val cvcState = MutableStateFlow(FieldState())
// ...
}
class MyScreen : ComponentActivity() {
val viewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Column {
CardNumberField()
CvcNumberField()
}
}
}
@Composable
fun CvcNumberField() {
viewModel.cvcField.ComposeUI(
onValueChange = { viewModel.cvcState.value = it },
modifier = Modifier.fillMaxWidth(),
onFocused = { /* handle focus */ },
onBlur = { /* handle blur */ }
)
}
}
```
### Additional Fields
The SDK also provides an AdditionalFields class that can be used to collect additional information from the user. The class is initialized with a type of the field and can be used to collect the following types of data:
* `CARDHOLDER_NAME` - to collect the cardholder name from the user.
In the future, the following fields will be added:
* `EMAIL` - to collect the email from the user.
* `BILLING_ADDRESS_LINE_1` - to collect the address details from the user.
* `BILLING_ADDRESS_LINE_2` - to collect the address details from the user.
* `BILLING_ADDRESS_LINE_3` - to collect the address details from the user.
* `BILLING_ADDRESS_POSTAL_CODE` - to collect the address details from the user.
* `BILLING_ADDRESS_CITY` - to collect the address details from the user.
#### Code sample
```kotlin theme={null}
class MyViewModel : ViewModel() {
val cardholderNameField = DataField(AdditionalDataTypes.CARDHOLDER_NAME)
val cardholderError = MutableStateFlow(false)
val cardholderNameState = MutableStateFlow(AdditionalDataFieldState())
// ...
}
```
### Tokenization
Once the user has filled in the fields, the data can be tokenized using the `tokenizeCard()` function of the `CardHandler` interface.
To create an instance of the `CardHandler` interface, you can use the `cardHandler()` function of the `Hellgate` SDK object. This section
is followed by the SDK-interface for reference. Please make sure to provide the base URL of the Hellgate® API as a parameter according
to your Hellgate® usage scenario. As a second parameter, you will need to provide the `session_id` that you received from the Hellgate®
API when you initialized the session on the server side.
Once created, you can initialize a Hellgate® Object which helps you to handle a session.
#### SDK Interface
```kotlin theme={null}
fun initHellgate(hgBaseUrl: String = HELLGATE_URL, sessionId: String): Hellgate
interface Hellgate {
@MainThread
suspend fun fetchSessionStatus(): SessionState
@MainThread
suspend fun cardHandler(): Result
}
enum class SessionState {
REQUIRE_TOKENIZATION,
COMPLETE,
WAITING,
UNKNOWN
}
```
#### Code sample
```kotlin theme={null}
class MyViewModel : ViewModel() {
val sessionState = MutableStateFlow(null)
fun createNewSession() {
viewModelScope.launch {
val sessionId: String = yourShopBackendClient().createSession().sessionId.orEmpty()
sessionState.value = SessionState.UNKNOWN
hellgate = initHellgate(HELLGATE_BASE_URL, sessionId)
}
}
fun fetchSessionStatus() {
viewModelScope.launch {
val sessionStatus = hellgate.fetchSessionStatus()
sessionState.value = sessionStatus
}
}
}
```
After acquiring a Hellgate® object, you can fetch the session status and create a card handler object to tokenize the card data. Fetching the session status will return a `SessionState` object which can be used to determine the state of the session. If the session is in the state `REQUIRE_TOKENIZATION` you can proceed with tokenizing the card data. After the card data was handed in successfully, the session state will change to `COMPLETE`. To hand in card data please create a card handler object by calling the `cardHandler()` function of the `Hellgate` object. Now the`tokenizeCard()` function can be used to tokenize the card data by handing over the classes of the card number, expiry date and CVC number fields. Also in case you collected additional data, you can hand over a list of `DataField` objects to the function. The function will return a `TokenizeCardResponse` object. In case the tokenization was successful, the response will be of type `TokenizeCardResponse.Success` and contain the ID of the token. In case the tokenization failed, the response will be of type `TokenizeCardResponse.Failure` and contain a message and an optional throwable.
#### SDK Interface
```kotlin theme={null}
interface CardHandler {
suspend fun tokenizeCard(
cardNumberField: CardNumberField,
cvcNumberField: CvcNumberField,
expiryDateField: ExpiryDateField,
additionalData: List = emptyList(),
): TokenizeCardResponse
}
sealed class TokenizeCardResponse {
data class Success(val id: String) : TokenizeCardResponse()
data class Failure(
val message: String,
val validationErrors: List = emptyList(),
) : TokenizeCardResponse()
}
// Possible validation errors
sealed interface CardDataValidationError {
val message: String
}
data object InvalidCardNumber : CardDataValidationError {
override val message: String = "Invalid card number"
}
data object InvalidExpiryDate : CardDataValidationError {
override val message: String = "Invalid expiry date"
}
data object InvalidCvc : CardDataValidationError {
override val message: String = "Invalid cvc"
}
```
#### Code sample
```kotlin theme={null}
fun submit() {
viewModelScope.launch {
hellgate.cardHandler().fold(
onSuccess = {
debugLog("$TAG Success, cardHandler created")
val response = it.tokenizeCard(
cardNumberField,
cvcField,
expiryDateField,
if (cardholderNameState.value.empty) emptyList() else listOf(cardholderNameField),
)
handleResponse(response)
textValue = response.toString()
},
onFailure = {
debugLog("$TAG Failure, cardHandler not created: ${it.message}")
},
)
}
}
private fun handleResponse(response: TokenizeCardResponse) {
when (response) {
is TokenizeCardResponse.Success -> {
debugLog("$TAG Tokenization successful, token ID: ${response.id}")
textValue = "Token ID: ${response.id}"
sessionState.value = SessionState.COMPLETED
}
is TokenizeCardResponse.Failure -> {
debugLog("$TAG Tokenization failed: ${response.message}, Validation Errors: ${response.validationErrors}")
textValue = "Error: ${response.message}"
sessionState.value = SessionState.FAILURE
}
}
}
```
# iOS SDK
Source: https://developer.hellgate.io/platform/resources/sdks/ios-sdk
The iOS SDK enables you to capture credit card data, additional personal data, and process them to create a Hellgate® Token. This token can then be used to process payments with the Hellgate® API.
The SDK is written in Swift and is available as an iOS dependency. It aims to provide a set of UI components and helpers that can be used to collect payment method data from the user with ease.
## Installation[](#installation "Direct link to Installation")
Installation can be done in a number of ways. Pick the distribution method that best suits your project:
### CocoaPods[](#cocoapods "Direct link to CocoaPods")
The SDK is available on [CocoaPods](https://cocoapods.org/pods/Hellgate-iOS-SDK). Add the following line to your `Podfile`:
```ruby theme={null}
pod 'Hellgate-iOS-SDK'
```
### Carthage[](#carthage "Direct link to Carthage")
1. Add the following line to your `Cartfile`:
```ruby theme={null}
github "starfish-codes/hgate2-ios-headless-sdk"
```
2. Run in same directory as your `Cartfile`:
```bash theme={null}
carthage update --use-xcframeworks
```
3. Add the built XCFrameworks to your project under "Frameworks and Libraries"
### Swift Package Manager[](#swift-package-manager "Direct link to Swift Package Manager")
The SDK is available on [Swift Package Index](https://swiftpackageindex.com/starfish-codes/hgate2-ios-headless-sdk). Add the package via Xcode from `https://github.com/starfish-codes/hgate2-ios-headless-sdk.git`
## Usage[](#usage "Direct link to Usage")
The SDK provides a set of UI components that can be used to collect payment method data from the user.
The components are composed of the following separate fields:
* `CardNumberView` - A View that collects card details from the user.
* `ExpiryDateView` - A View that collects the expiry date of the card from the user.
* `CvcView`- A View that collects the CVC of the card from the user.
First you'll need to import the project:
```swift theme={null}
import Hellgate_iOS_SDK
```
### User Interface[](#user-interface "Direct link to User Interface")
#### Initialization of the UI Components[](#initialization-of-the-ui-components "Direct link to Initialization of the UI Components")
These components are intended to be used in a SwiftUI project. The validity of the users entered data can be listened in on by creating a `@State` property on your parent view.
#### ViewState[](#viewstate "Direct link to ViewState")
Each view below requires a binding to a `ViewState` property. The `ViewState` of each component is updated as soon as their related component changes.
##### SDK Interface[](#sdk-interface "Direct link to SDK Interface")
```swift theme={null}
public enum ComponentState: String {
case complete
case incomplete
case blank
case invalid
}
public struct ViewState {
public let state: ComponentState
}
```
##### Code Sample[](#code-sample "Direct link to Code Sample")
```swift theme={null}
struct ContentView: View {
@State var cardNumberViewState = ViewState(state: .blank)
@State var expiryViewState = ViewState(state: .blank)
@State var cvcViewState = ViewState(state: .blank)
// ...
}
```
#### CardNumberView[](#cardnumberview "Direct link to CardNumberView")
The `CardNumberView` view is used to collect the card number from the user. It can be initialized with the card brand image either on the leading or trailing side of the input or hidden.
##### Code Sample[](#code-sample-1 "Direct link to Code Sample")
```swift theme={null}
CardNumberView(viewState: $cardNumberViewState, image: .leading)
.border()
struct ContentView: View {
@State var cardNumberViewState = ViewState(state: .blank)
var body: some View {
CardNumberView(viewState: $cardNumberViewState, image: .leading)
.border()
}
}
```
#### ExpiryDateView[](#expirydateview "Direct link to ExpiryDateView")
The `ExpiryDateView` view is used to collect the expiry date of the card from the user.
##### Code Sample[](#code-sample-2 "Direct link to Code Sample")
```swift theme={null}
struct ContentView: View {
@State var expiryViewState = ViewState(state: .blank)
var body: some View {
ExpiryDateView(viewState: $expiryViewState)
.border()
}
}
```
#### CvcView[](#cvcview "Direct link to CvcView")
The `CvcView` view is used to collect the CVC or CVV number of the card from the user.
##### Code Sample[](#code-sample-3 "Direct link to Code Sample")
```swift theme={null}
struct ContentView: View {
@State var cvcViewState = ViewState(state: .blank)
var body: some View {
CvcView(viewState: $cvcViewState, length: .cvc)
.border()
}
}
```
#### Additional Fields[](#additional-fields "Direct link to Additional Fields")
The `AdditionalFieldsView` is used to capture additional information about the card holder. The view is initialized with a type of the field and can be used to collect the following types of data:
* `CARDHOLDER_NAME` - to collect the cardholder name from the user. In the future, the following fields will be added:
* `EMAIL` - to collect the email from the user.
* `BILLING_ADDRESS_LINE_1` - to collect the address details from the user.
* `BILLING_ADDRESS_LINE_2` - to collect the address details from the user.
* `BILLING_ADDRESS_LINE_3` - to collect the address details from the user.
* `BILLING_ADDRESS_POSTAL_CODE` - to collect the address details from the user.
* `BILLING_ADDRESS_CITY` - to collect the address details from the user.
##### Code Sample[](#code-sample-4 "Direct link to Code Sample")
```swift theme={null}
struct ContentView: View {
var body: some View {
AdditionalFieldsView(type: .CARDHOLDER_NAME)
.border()
}
}
```
### Tokenization[](#tokenization "Direct link to Tokenization")
Once the user has filled in the fields, the data can be tokenized using the `tokenizeCard()` function of the `CardHandler` interface. To create an instance of the `CardHandler` interface, you can use the `cardHandler()` function of the Hellgate® SDK object. This section is followed by the SDK-interface for reference.
Please make sure to provide the base URL of the Hellgate® API as a parameter according to your Hellgate® usage scenario. As a second parameter, you will need to provide the `session_id` that you received from the Hellgate® API when you initialized the session on the server side. See the section Tokenize on the Web for more information.
Once created, you can initialize a Hellgate® Object which helps you to handle a session.
##### SDK Interface[](#sdk-interface-1 "Direct link to SDK Interface")
```swift theme={null}
func initHellgate(baseUrl: URL, sessionId: String) async -> Hellgate
protocol Hellgate {
func fetchSessionStatus() async -> SessionState
func cardHandler() async -> Result
}
enum SessionState: String {
case REQUIRE_TOKENIZATION
case WAITING
case COMPLETED
case UNKNOWN
}
```
##### Code Sample[](#code-sample-5 "Direct link to Code Sample")
```swift theme={null}
import Hellgate_iOS_SDK
class ContentViewViewModel: ObservableObject {
private var hellgate: Hellgate?
@Published var secretKey = ""
@Published var sessionId = ""
@Published var sessionState: SessionState?
@MainActor
func initSession() async {
self.sessionId = await fetchSessionId()
self.hellgate = await initHellgate(baseUrl: HELLGATE_URL, sessionId: sessionId)
}
@MainActor
func sessionStatus() async {
guard let hellgate = self.hellgate else { return }
self.sessionState = await hellgate.fetchSessionStatus()
}
}
```
After acquiring a Hellgate® object, you can fetch the session status and create a card handler object to tokenize the card data. Fetching the session status will return a SessionState enum which can be used to determine the state of the session. If the session is in the state `REQUIRE_TOKENIZATION` you can proceed with tokenizing the card data. After the card data was handed in successfully, the session state will change to `COMPLETE`. To hand in card data please create a card handler object by calling the `cardHandler()` function of the Hellgate® object. Now the `tokenizeCard()` function can be used to tokenize the card data by handing over the classes of the card number, expiry date and CVC number fields.
Also, in case you collected additional data, you can hand over a list of DataField objects to the function. The function will return a TokenizeCardResponse object. In case the tokenization was successful, the response will be of type `TokenizeCardResponse.Success` and contain the ID of the token. In case the tokenization failed, the response will be of type `TokenizeCardResponse.Failure` and contain a message.
##### SDK Interface[](#sdk-interface-2 "Direct link to SDK Interface")
```swift theme={null}
protocol CardHandler {
func tokenizeCard(
_ cardNumberView: ViewState,
_ cvcView: ViewState,
_ expiryView: ViewState,
_ additional: [AdditionalFieldType: ViewState]
) async -> Result
}
enum TokenizeCardResponse {
public struct Success: Decodable {
public let id: String
}
public struct Failure: Error, Decodable {
let message: String
var localizedDescription: String { message }
}
}
```
##### Code Sample[](#code-sample-6 "Direct link to Code Sample")
```swift theme={null}
@MainActor
func tokenize() async {
guard let hellgate = self.hellgate else { return }
let result = await hellgate.cardHandler()
if case let .success(handler) = result {
let response = await handler.tokenizeCard(
cardNumberViewState,
cvcViewState,
expiryViewState,
[:]
)
switch response {
case let .success(result):
print("Token: \(result.id)")
case let .failure(err):
print(err.localizedDescription)
}
}
}
```
# API
Source: https://developer.hellgate.io/platform/resources/sdks/web-sdk/api
Web SDK API reference for client sessions and payment processing.
## Create Client
This method will create and initialise the Hellgate® client using an existing `session_id`.
```javascript theme={null}
const { Hellgate } = window;
const client = await Hellgate.init('7f2c9460-7e2e-403f-a08a-bc58cdcaea83', {
base_url: 'https://sandbox.hellgate.io',
});
```
| Parameter | Type | Required? | Description |
| - | - | - | - |
| sessionID | String | Yes | The session id that was handed over to the integrator as part of an action requirement. |
| options | Object | No | [Options](#element-options) to customise the form to specific requirements |
### Options
| Attribute | Type | Description |
| - | - | - |
| base\_url | String | Set custom Hellgate® backend. Default -`https://api.hellgate.io` |
| challenge\_3ds\_container | HTMLElement | Custom DOM container for rendering 3D Secure Challenge iframe. Default - `undefined` |
| challenge\_3ds\_label\_text | String | Display custom label text for 3D Secure Challenge iframe |
### Session Complete
This event is called once the session is completely finished.
```javascript theme={null}
client.onSessionComplete((result) => {
// handling logic
});
```
The handler receives a `result` object.
#### Session Result
| Attribute | Type | Description |
| - | - | - |
| status | "success" \| "failure" \| "pending" | Status of the current processing |
| data | Object | Result data |
#### Session Result status
| Name | Description |
| - | - |
| success | The SDK session was completed successfully. Result could be found in the `data` attribute |
| failure | The SDK session failed. Failure reason and reason code could be found in the `data` attribute |
| pending | The SDK session concluded successfully; however, the ultimate outcome of the operation initiated by the session remains indeterminate due to its asynchronous nature. The definitive results will be delivered to the backend via webhook or can be retrieved through an API request. |
## Create Card Handler
In order to process card payments (and later other payment methods as well), a handler has to be obtained from the client.
```javascript theme={null}
const cardHandler = await client.use('CARD');
```
## Reset Card Handler
This method will remove the card form or card fields from the client, disconnect handlers and unmount the fields from the DOM.
```javascript theme={null}
cardHandler.reset();
```
## Handling Cards
### Create Card Form
This method will create a new one-line card form.
```javascript theme={null}
const cardForm = cardHandler.createForm(options);
```
#### Parameters
| Parameter | Type | Required? | Description |
| - | - | - | - |
| options | Object | No | [Options](#element-options) to customise the form to specific requirements. |
### Create Card Fields
This method will create the full set of card fields as shown below in the demo.
```javascript theme={null}
const { cardNumber, expiryDate, securityCode } = cardHandler.createFormFields(options);
```
#### Parameters
| Parameter | Type | Required? | Description |
| - | - | - | - |
| options | Object | No | [Options](#element-options) to customise the form fields to specific requirements. The options can be prefixed with `cardNumber: {}`, `expiryDate: {}`, and `securityCode: {}` to apply them specifically (e.g. `cardNumber: {placeholder: 'Custom Placeholder'}`). |
| options.expiryDateElement | String | `"combined" \| "separate"` | `combined` - expiration month and year is a single form field. `separate` - expiration month and year are two separate fields. Default: `combined`. |
### Create Text Field
The "text" element type is a secure replacement for the `` tag and enables collecting user string data like Cardholder Name as demonstrated.
```javascript theme={null}
cardHandler.createTextField({ placeholder: 'Cardholder Name' });
```
The created `TextField` can be directly passed as a property for `additionalData` and the value does not need to be extracted.
#### Parameters
| Parameter | Type | Required? | Description |
| - | - | - | - |
| options | Object | No | [Options](#element-options) to customise the form fields to specific requirements. |
### 3D-Secure
3D Secure handling works out of the box with the SDK and usually doesn't require any extra code.
### Process
This method will read the data from the card form or the card fields and send them to processing. Prerequisite is that card fields or a card form was created before. A loading indicator can be shown until the promise is resolved.
```javascript theme={null}
const result = await cardHandler.process({
// cardholderTextField can be created by cardHandler.createTextField()
// the value from the text field will be extracted automatically during processing
cardholder_name: cardholderTextField,
});
```
We recommend performing a preliminary check to ensure that the card [data](#formstatechange) is complete and valid before calling this method. Otherwise, the promise returned by the `cardHandler.process()` call will be rejected with an [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object.
#### Parameters
| Parameter | Type | Required? | Description |
| - | - | - | - |
| additionalData | Object | No | Further information that needs to be passed into the processing. |
#### Additional Data
| Attribute | Type | Description |
| - | - | - |
| cardholder\_name | String \| TextField | The name of the cardHolder |
| email | String \| TextField | Email address of the customer |
| billing\_address.line1 | String \| TextField | The first line of the address |
| billing\_address.line2 | String \| TextField | The second line of the address |
| billing\_address.line3 | String \| TextField | The third line of the address |
| billing\_address.postal\_code | String \| TextField | The postal code of the address |
| billing\_address.city | String \| TextField | The name of the city |
| billing\_address.country | String \| TextField | The three letter country code following [ISO3166-Alpha3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) |
#### Token lifecycle
Pass these fields in the same object as the additional data to control how long the resulting token is retained. Both `process()` and `tokenize()` accept them.
| Attribute | Type | Description |
| - | - | - |
| ephemeral | Boolean | When `true`, the token is short-lived: Guardian deletes it after a short TTL (15 minutes by default). When `false`, the token is persisted until it is deleted through the API — set it to `false` only on cardholder consent. |
| expiration\_date | String | An ISO-8601 timestamp setting an explicit expiration for the token. It must lie in the future, at most 30 days ahead; otherwise the session completes with `status: "failure"` and `reason_code: "VALIDATION_ERROR"`. When supplied, it takes precedence and `ephemeral` is ignored. |
When both fields are omitted, the token is persisted. An absent flag is treated as a legacy client that predates these fields, so the pre-lifecycle behaviour is kept for backward compatibility. Don't rely on this implicit default — pass `ephemeral` explicitly, and persist only after the cardholder consented.
For a "Save my card" consent UX, wire the checkbox straight into the flag:
```javascript theme={null}
const result = await cardHandler.process({
cardholder_name: cardholderTextField,
// persist the token only when the cardholder ticked "Save my card"
ephemeral: !saveMyCardCheckbox.checked,
});
```
#### Session lifecycle modes
The backend assigns every tokenization session a lifecycle mode when the session is created. The SDK exposes it via `cardHandler.getLifecycle()`:
| Mode | When | Effect on `process()` / `tokenize()` |
| - | - | - |
| `user_choice` | Default | Your `ephemeral` / `expiration_date` arguments are sent as provided. |
| `ephemeral_only` | The session was created with an explicit TTL (`expires_in`) | The SDK always requests an ephemeral token; your lifecycle arguments are ignored and the session's TTL applies. |
| `persistent_only` | Network-token sessions | The SDK always requests a persistent token; your lifecycle arguments are ignored. |
Use the mode to adapt your UI — for example, only render the "Save my card" checkbox when the cardholder actually has a choice:
```javascript theme={null}
const showSaveMyCard = cardHandler.getLifecycle() === 'user_choice';
```
#### Result
Session result [data](#session-result)
#### Result status
Session result [status](#session-result-status)
# Elements API
The Elements API allows to interact with the created card form or the card fields.
## Mount Element
This operation mounts an element to the DOM at the specified element.
```javascript theme={null}
await cardForm.mount('#my-card-form-id');
```
### Parameters
| Parameter | Type | Required? | Description |
| - | - | - | - |
| selector | String | Yes | A CSS-selector that identifies the container in the DOM to where the element will be mounted |
## Update Element
This operations allows to change the options on an element. Please note that not all options can be changed.
```javascript theme={null}
cardNumberField.update({ icon: 'none' });
```
### Parameters
| Parameter | Type | Required? | Description |
| - | - | - | - |
| options | Object | No | The [options](#element-options) to customise the element. |
## Unmount Element
This operation removes an element from the DOM.
```javascript theme={null}
cardNumberField.unmount();
```
## Element Values / States
### Focus
Set the focus on an element's input.
```javascript theme={null}
cardNumberField.focus();
```
### Clear
Clear the value of an element.
```javascript theme={null}
cardNumberField.clear();
```
### Blur
Blur an element's input.
```javascript theme={null}
cardNumberField.blur();
```
## Element Options
| Attribute | Element | Type | Description |
| - | - | - | - |
| style | All | Object | [Data](#element-styles) that defines the styling of the element. |
| height | All | String | [CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/height) to customise the height of the element |
| disabled | All | Boolean | Set the disabled state of the form field(s). |
| autocomplete | All | String | String used to set the [autocomplete attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) of the input(s). Expected values are: off (default), or on. |
| placeholder | text, cardNumber, cardExpirationDate, cardVerificationCode | String | String to customise the placeholder attribute of the form field. |
| ariaLabel | text, cardNumber, cardExpirationDate, cardVerificationCode | String | String to customise the aria-label attribute of the form field. |
| icon | card, cardNumber | String | String to determine the position of the icon in the cardNumber field. `left` is the default value. It can be overwritten to `right` and to `none` in order to hide the icon entirely. |
| schemes | card, cardNumber | String\[] | Whitelist of card schemes which are supported by the merchant. Available schemes: `visa`, `mastercard`, `american-express`, `discover`, `diners-club`, `jcb` `unionpay`. The input of a restricted scheme will lead to a validation error in the form. All schemes are supported by default. |
## Element Styles
The form fields are encapsulated into iframes to allow for maximum protection of sensitive data. This means that CSS from the embedding page cannot be propagated directly into the form or the fields.
```javascript theme={null}
cardNumberField.update({
style: {
fonts: ['https://fonts.googleapis.com/css2?family=Playfair:wght@300&display=swap'],
base: {
color: '#fff',
fontWeight: 500,
fontFamily: '"Playfair"',
fontSize: '16px',
'::placeholder': {
color: '#6b7294',
},
':disabled': {
backgroundColor: '#ffff3b',
},
},
invalid: {
color: '#ffa474',
},
},
});
```
| Attribute | Required? | Description |
| - | - | - |
| fonts | No | List of URLs to fonts on the Google API. |
| base | No | Basic styling of the element. The other variants will use it as baseline. |
| complete | No | Variant of the baseline for an element with completed input. |
| empty | No | Variant of the baseline for an element with empty input. |
| invalid | No | Variant of the baseline for an element with invalid input. |
You can customise the elements using these pseudo-classes and pseudo-elements inside each variant using a nested object:
* `:hover`
* `:focus`
* `:disabled`
* `::placeholder`
* `::selection`
These CSS properties are supported in terms of styling:
* backgroundColor
* color
* fontFamily
* fontSize
* fontSmooth (will be mapped to user-agent naming automatically)
* fontStyle
* fontVariant
* fontWeight
* lineHeight
* letterSpacing
* textAlign
* padding
* textDecoration
* textShadow
* textTransform
# Events
Both the clients and the elements send out events so that solutions can actively react to changes in state.
## Card Handler Events
### FormStateChange
This event notifies every time the card form fields state changes.
```javascript theme={null}
cardHandler.onStateChange((state) => {
// handling logic
});
```
The handler receives an aggregated `state` object that is derived from all card fields states.
```json theme={null}
{
"valid": false,
"complete": false,
"empty": true,
"error": "cardNumber is not complete"
}
```
| Attribute | Type | Description |
| - | - | - |
| valid | Boolean | Indicates that all fields content successfully passed validation. |
| complete | Boolean | Indicates that all fields are valid and maskSatisfied properties are true |
| empty | Boolean | Form will be empty only if all inputs are |
| error | String | Human readable error message with an explanation why `valid: false` |
| errorCode | String | Values are `NOT_COMPLETE`, `SCHEME_NOT_SUPPORTED`, `LUHN_CHECK_FAILED` and `INVALID_EXPIRY_DATE` |
## 3D-Secure Events
In standard cases 3D Secure handling works out of the box with the SDK and usually doesn't require any extra code. However, there are some events that can be used to handle the 3DS Challenge experience in the UI.
In order to use the 3DS Handler, it has to be obtained from the client:
```javascript theme={null}
const threeDSHandler = await client.use('3DS');
```
### Decoupled Authentication
Decoupled authentication can be supported by the SDK with a specific event.
```javascript theme={null}
threeDSHandler.onDecoupledAuth((cardholderInfo) => {
// handle decoupled flow here and display cardholderInfo on the UI
// to inform the customer how they should complete 3DS authentication
});
```
| Parameter | Type | Description |
| - | - | - |
| cardholderInfo | String | Instructions from the card issuer what method the customer should use to complete 3DS authentication. For example, mobile banking app |
### Start Challenge
This event is called once the 3DS Challenge is started. It can be used to show a loading indicator or to inform the customer about the ongoing process.
```javascript theme={null}
threeDSHandler.onStartChallenge(() => {
// called once 3DS Challenge is started
});
```
### Challenge Finished
This event is called once the 3DS Challenge is finished. It can be used to hide the loading indicator or to inform the customer about the result.
```javascript theme={null}
threeDSHandler.onChallengeFinished(() => {
// called when 3DS Handler finishes the task
});
```
## Element Events
### Change
This event notifies that the value of an element has changed. By default this event is emitted `onBlur` which can be overwritten with the element options.
```
cardNumberField.on('change', (changeEvent) => { // handling logic});
```
The handler receives a ChangeEvent with information about the state of the element.
```
{ "complete": true, "valid": false, "empty": false, "error": "Card Number Luhn check failed", "cardBrand": "amex"}
```
| Attribute | Element | Type | Description |
| - | - | - | - |
| valid | All | Boolean | Indicates that the content successfully passed validation. |
| empty | All | Boolean | Indicates that the element is empty. |
| error | All | String | Human readable error message with an explanation why `valid: false` |
| cardBrand | CardNumber | String | Values are `amex`, `visa`, `mastercard`, `diners`, `jcb`, and `unionpay`. |
### Focus
This event indicates that an element is focussed.
```javascript theme={null}
cardNumberField.on('focus', () => {
// handling logic
});
```
### Blur
This event indicates that an element lost focussed.
```javascript theme={null}
cardNumberField.on('blur', () => {
// handling logic
});
```
### Key Down
This event indicates that a key was pressed on the element.
```javascript theme={null}
cardNumberField.on('keydown', (keyDownEvent) => {
// handling logic
});
```
The handler receives a KeyDownEvent with information about the state of the element.
```json theme={null}
{
"key": "enter",
"ctrlKey": false,
"altKey": false,
"shiftKey": false,
"metaKey": false
}
```
| Attribute | Type | Description |
| - | - | - |
| key | String | Indicator of the key that was pressed. Can be `Enter` or `Escape`. |
| ctrlKey | Boolean | Indicates if the control key was pressed when the event occurred. |
| altKey | Boolean | Indicates if the alt / option key was pressed when the event occurred. |
| shiftKey | Boolean | Indicates if the shift key was pressed when the event occurred. |
| metaKey | Boolean | Indicates if the meta (e.g. command on a Mac) key was pressed when the event occurred. |
# Overview
Source: https://developer.hellgate.io/platform/resources/sdks/web-sdk/overview
Headless Web SDK for payment experiences on the web.
In order to make use of the Web SDK you need to create a client-sharable, short-lived secret. This secret is called a `session` as it represents a session between your web application and the Hellgate®.
Create a session for tokenization using the session API.
```bash title="Example: Create session" theme={null}
curl --request POST \
--url https://api.hellgate.io/tokens/session \
--header 'content-type: application/json'
```
The response includes the `session_id` of the created session.
```json title="Example: Session response" theme={null}
{
"session_id": "7f2c9460-7e2e-403f-a08a-bc58cdcaea83"
}
```
Want to confirm the session works before writing any browser code? Paste the `session_id` into the [WebSDK testing page](/platform/resources/testing/web-sdk) to run the full card flow against it.
Send the `session_id` to your web application in the customer's browser. The `session_id` is safe to share with the client.
You must not distribute your server-side API keys to the clients. Use the provided `session_id`, which is short-lived (with a default of 15 minutes) and has a very limited scope. This protects you from malicious acts.
After the `session_id` is handed over to the client, initialise the headless SDK.
### Load the SDK
The SDK is distributed via our CDN or from NPM.
```bash title="Example: Install via NPM" theme={null}
npm install --save @starfish-codes/hellgate
```
```html title="Example: Load via CDN" theme={null}
```
### Initialise the SDK
With the `session_id` and the loaded SDK, initialise a headless client for your browser session.
```javascript title="Example: Initialise client" theme={null}
import { Hellgate } from '@starfish-codes/hellgate';
// Create the Hellgate client. Make sure you await the result of the
// asynchronous initialisation, as subsequent actions will rely on it.
const client = await Hellgate.init('7f2c9460-7e2e-403f-a08a-bc58cdcaea83', {
base_url: 'https://sandbox.hellgate.io',
});
```
The headless client keeps a secure connection to the Hellgate® backend. Connect it with your application to proceed.
Hellgate's Headless SDK enables secure card payment data entry, yet is fully embedded in your web application. The secure communication channel between the SDK and the Hellgate® allows the sensitive card data to be exchanged for so-called tokens. These are made available to you as a payment method.
Use the `CARD` handler to tokenize cardholder data.
```javascript title="Example: Get card handler" theme={null}
const cardHandler = await client.use('CARD');
```
Based on the handler, two form types can be rendered in your front-end.
### One-Line Card Form
A compact way to collect card details: separate entry fields rendered as one unit.
```javascript title="Example: One-line card form integration" theme={null}
const { Hellgate } = window;
const client = await Hellgate.init('d5529f03-e84a-4a43-867c-b3412a097e63', {
base_url: 'https://sandbox.hellgate.io',
});
const cardHandler = await client.use('CARD');
const cardForm = cardHandler.createForm({
style: {
fonts: ['https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;500;600;700;800&display=swap'],
base: {
fontFamily: 'Nunito, sans-serif',
color: '#111',
fontSize: '16px',
'::placeholder': { color: '#6b7280' },
},
},
});
const cardholderField = cardHandler.createTextField();
cardForm.mount('#my-form-element');
cardholderField.mount('#cardholder-element');
const submitButton = document.getElementById('my-submit-button');
submitButton.addEventListener('click', async () => {
try {
const result = await cardHandler.process({
cardholder_name: cardholderField,
});
const resultElement = document.getElementById('result');
const errorElement = document.getElementById('error');
if (result.status === 'success' || result.status === 'pending') {
resultElement.textContent = 'Processing has been successfully completed';
errorElement.textContent = '';
} else {
resultElement.textContent = '';
errorElement.textContent = result.data.reason;
}
} catch (err) {
// handle error (e.g. network issue or backend error)
}
});
```
### Separated Card-Data Fields
For more flexibility in layout, create individual elements and mount them separately.
```javascript title="Example: Separated card fields" theme={null}
const { Hellgate } = window;
const client = await Hellgate.init('d5529f03-e84a-4a43-867c-b3412a097e63', {
base_url: 'https://sandbox.hellgate.io',
});
const cardHandler = await client.use('CARD');
const { cardNumber, expiryDate, securityCode } = cardHandler.createFormFields({
style: {
base: {
color: '#111',
fontSize: '14px',
},
},
});
await Promise.all([
cardNumber.mount('#my-card-number-element'),
expiryDate.mount('#my-expiry-date-element'),
securityCode.mount('#my-security-code-element'),
]);
const submitButton = document.getElementById('my-submit-button');
submitButton.addEventListener('click', async () => {
try {
const result = await cardHandler.process({
cardholder_name: 'Cardholder Name',
});
const resultElement = document.getElementById('result');
const errorElement = document.getElementById('error');
if (result.status === 'success' || result.status === 'pending') {
resultElement.textContent = 'Processing has been successfully completed';
errorElement.textContent = '';
} else {
resultElement.textContent = '';
errorElement.textContent = result.data.reason;
}
} catch (err) {
// handle error
}
});
```
### Separated expiration month and year
Use `expiryDateElement: 'separate'` to get distinct month and year fields.
```javascript title="Example: Separate month and year fields" theme={null}
const { cardNumber, expiryMonth, expiryYear, securityCode } = cardHandler.createFormFields({
style: {
base: {
color: '#111',
fontSize: '14px',
},
},
expiryDateElement: 'separate',
});
await Promise.all([
cardNumber.mount('#my-card-number-element'),
expiryMonth.mount('#my-expiry-month-element'),
expiryYear.mount('#my-expiry-year-element'),
securityCode.mount('#my-security-code-element'),
]);
```
# Network Token
Source: https://developer.hellgate.io/platform/resources/testing/network-token
Test network token provisioning and cryptogram generation with the Hellgate Cloud Network Token Sandbox
Hellgate Cloud provides a built-in **Network Token Sandbox** for testing network tokens on Test tier deployments. The Network Token Sandbox serves as the default backend for network token provisioning and enables you to test network token functionality across both Commerce and Guardian products.
## Overview
The Hellgate Cloud Network Token Sandbox supports two modes of network token testing:
* **Standard network token testing**: Generates network tokens from PAN data and allows you to request cryptograms (payment data) for them
* **Deterministic network tokens**: Uses the FPAN (Fundamental PAN) of the underlying card as the TPAN (Token PAN) for transitive testing scenarios
Both modes work seamlessly on Commerce and Guardian, allowing you to test the complete network token lifecycle from provisioning through cryptogram generation and payment authorization.
## Standard Network Token Testing
When you provision a network token using PAN data, the Network Token Sandbox:
1. Accepts the FPAN and associated card data
2. Generates a network token (TPAN - Token PAN) from the FPAN
3. Associates the network token with your tokenized card
4. Enables cryptogram requests for payment authorization
This standard behavior allows you to test the complete network token lifecycle, from provisioning through cryptogram generation and payment authorization.
## Deterministic Network Tokens
For advanced testing scenarios involving transitive testing with acquirers and processors, Hellgate Cloud provides deterministic network tokens.
Deterministic TPANs are **not active by default**. Contact support to activate this feature for your account.
### How Deterministic Network Tokens Work
Deterministic network tokens use the FPAN (Fundamental PAN) of the underlying card as the TPAN (Token PAN). This means:
* The network token (TPAN) will be identical to the original card PAN (FPAN)
* Cryptograms can be deterministically generated for the same TPAN
* You can create predictable, reproducible testing scenarios
### When to Use Deterministic Network Tokens
Deterministic network tokens are particularly useful for:
* **Transitive testing**: Testing integrations with connected sandboxes (e.g., acquirer or PSP sandboxes)
* **Predictable scenarios**: Creating reproducible test cases where the same PAN always generates the same network token
* **Third-party sandbox integration**: Enabling access to sandbox behavior on connected third-party environments (e.g., acquirer or PSP test systems)
### Benefits
With deterministic network tokens, you can:
* Provision network tokens and deterministically generate the TPAN with a cryptogram
* Test end-to-end flows through multiple systems (Hellgate Cloud → Acquirer → Processor)
* Maintain consistency across test runs
* Simplify integration testing with external sandbox environments
## Testing Workflow
Follow these steps to test network tokens:
Create a network token from PAN data using standard provisioning or deterministic mode (if enabled).
For detailed API documentation, refer to:
* [Commerce Network Tokens API](/products/commerce/v2/api-reference/tokens/overview)
* [Guardian Network Tokens API](/products/guardian/api-reference/network/create-token)
Generate payment data (cryptogram) for the network token. The cryptogram is used during payment authorization as proof of token validation.
Use the network token and cryptogram for payment authorization with your PSP or acquirer.
Confirm the expected behavior based on your test scenario and validate that the network token and cryptogram work correctly.
## Test Cards
Use the test cards provided in our [Test Cards documentation](/platform/resources/testing/test-card) to test network token scenarios. These cards support various network tokenization scenarios including:
* Successful provisioning
* Eligibility failures
* Payment data request failures
# Test Cards
Source: https://developer.hellgate.io/platform/resources/testing/test-card
You must not perform tests with **real** card data on your **Sandbox** account.
## Network Tokenization[](#network-tokenization "Direct link to Network Tokenization")
This section provides a list of test cards specifically designed for testing network tokenization scenarios. These cards can be used to simulate various network tokenization processes, allowing you to verify the functionality and reliability of your integration with our services.
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Network Tokenization | Any VISA Test-Card | Any | Any | Tokenized card with Network token status = 'Active' |
| Test unsuccessful Network Tokenization (Card not eligible) | 4000000000000101 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test successful Network Tokenization but failure on payment-data requests | 4000000000000002 | Any | Any | Tokenized card with Network token status = 'Active' / requests for payment-data will fail |
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Network Tokenization | Any Mastercard Test-Card | Any | Any | Tokenized card with Network token status = 'Active' |
| Test unsuccessful Network Tokenization (Card not eligible) | 5186009200935811 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Card not eligible) | 5204731940398145 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Card not eligible) | 5120340000000392 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test successful Network Tokenization but failure on payment-data requests | 2223000048430018 | Any | Any | Tokenized card with Network token status = 'Active' / requests for payment-data will fail |
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Network Tokenization | Any American Express Test-Card | Any | Any | Tokenized card with Network token status = 'Active' |
| Test unsuccessful Network Tokenization (Card not eligible) | 378734493671000 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test successful Network Tokenization but failure on payment-data requests | 371449635398431 | Any | Any | Tokenized card with Network token status = 'Active' / requests for payment-data will fail |
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Network Tokenization | Any Discover Test-Card | Any | Any | Tokenized card with Network token status = 'Active' |
| Test unsuccessful Network Tokenization (Card not eligible) | 6011000990139440 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test successful Network Tokenization but failure on payment-data requests | 6011000990139432 | Any | Any | Tokenized card with Network token status = 'Active' / requests for payment-data will fail |
### Visa Acceptance TMS
Use these cards when your Test tier provisions network tokens through the [Visa Acceptance Token Management Service (TMS) sandbox](https://developer.visaacceptance.com/docs/cybs/en-us/tms/developer/all/rest/tms/tms-create-request/tms-test-cards.html) instead of the Hellgate Cloud Network Token Sandbox.
Visa Acceptance documents these cards with `X` placeholders. Hellgate recognises only the exact numbers listed here. Any other digits in place of `X` are treated as a real card number and rejected on the Test tier.
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Network Tokenization | 4622943123100639 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful Network Tokenization | 4622943123100647 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful Network Tokenization | 4622943123100654 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful Network Tokenization | 4622943123100662 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful Network Tokenization | 4622943123100670 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful Network Tokenization | 4622943123100688 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful Network Tokenization | 4622943123100696 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test unsuccessful Network Tokenization (Card verification failed) | 4000000011000009 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Card not eligible) | 4001770011000006 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Card not allowed) | 4010057011000007 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Declined) | 4010057022000004 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Declined) | 4020057022000002 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Service unavailable) | 4010057033000001 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Service unavailable) | 4020057033000009 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (System error) | 4010057044000008 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (System error) | 4020057044000006 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Invalid request) | 4020057055000002 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful token for token (Card verification failed) | 4000010011000008 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful token for token (Card not eligible) | 4000010022000005 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful token for token (Card not allowed) | 4000010033000002 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful token for token (Service unavailable) | 4000010044000009 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful token for token (System error) | 4000010055000005 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful token for token (Invalid request) | 4000010088000006 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Network Tokenization | 5120342233150747 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful Network Tokenization | 5120343287499758 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful Network Tokenization | 5120350100064594 | Any | Any | Tokenized card with Network token status = 'Active' |
| Test successful token for token | Any Mastercard Test-Card | Any | Any | Tokenized card with Network token status = 'Active' |
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Network Tokenization | Any American Express Test-Card | Any | Any | Tokenized card with Network token status = 'Active' |
| Test unsuccessful Network Tokenization (Card not eligible) | 370000000000028 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Declined) | 370000000000002 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Service unavailable) | 370000000000119 | Any | Any | Tokenized card with Network token status = 'Failed' |
| Test unsuccessful Network Tokenization (Card not allowed) | 370000000000036 | Any | Any | Tokenized card with Network token status = 'Failed' |
## 3-D Secure[](#3-d-secure "Direct link to 3-D Secure")
In this section, you'll find a list of test cards designed to simulate various scenarios, allowing for comprehensive testing of your integration with our services.
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 4100000000000100 | Any | Any | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 4100000000600008 | Any | Any | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 4100000000005000 | Any | Any | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 4100000000100009 | Any | Any | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test unsuccessful Tokenization with ID\&V (Authentication Failed) | 4100000000300005 | Any | Any | No token issued with 3DS challenge. Enter the password "111111" to simulate the cardholder not being authenticated |
| Test unsuccessful Tokenization with ID\&V (Authentication Unavailable) | 4100000000400003 | Any | Any | No token issued with authentication unavailable, due to a simulated technical error with the ACS (Access Control Server) |
| Test unsuccessful Tokenization with ID\&V (Authentication Rejected) | 4100000000500000 | Any | Any | No token issued with the authentication being rejected by the ACS (Access Control Server) |
| Scenario | Card Number | Expiry Date | CVC | Expected Result |
| - | - | - | - | - |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 2222690420064590 | 12/2030 | 123 | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 5100000000000107 | Any. | Any | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 5100000000600005 | Any. | Any | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 5100000000005007 | Any. | Any | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test successful Tokenization with ID\&V (Challenge Authentication) | 5100000000100006 | Any. | Any | Tokenized card with 3DS challenge. Enter the password "123456" to complete the transaction |
| Test unsuccessful Tokenization with ID\&V (Authentication Failed) | 5100000000300002 | Any. | Any | No token issued with challenge. Enter the password "111111" to simulate the cardholder not being authenticated |
| Test unsuccessful Tokenization with ID\&V (Authentication Unavailable) | 5100000000400000 | Any. | Any | No token issued with authentication unavailable, due to a simulated technical error with the ACS (Access Control Server) |
| Test unsuccessful Tokenization with ID\&V (Authentication Rejected) | 5100000000500007 | Any. | Any | No token issued with the authentication being rejected by the ACS (Access Control Server) |
# Card Tokenization
Source: https://developer.hellgate.io/platform/resources/testing/web-sdk
Exercise the Web SDK card flow with a session, no front-end required.
The [Hellgate Cloud Web SDK Demo](https://demo.hellgate.dev/card) is a hosted front-end that drives the Web SDK flows end to end. Paste a `session_id` from your server, submit a card, and confirm the resulting token — all without building a browser integration first. Reach for it when you want to verify a session from your backend before wiring up the SDK in your own application.
The workbench covers four flows, exposed as tabs at the top of the page: **Card Tokenization**, **CVC2 Refresh**, **Card Elements**, and **3DS**. This page walks through the default **Card Tokenization** flow; the other tabs consume the same session and backend configuration.
## Prerequisites
A `session_id` from your backend — see the [Guardian](/products/guardian/api-reference/pci/create-token) and [Commerce v2](/products/commerce/v2/api-reference/tokens_create/request-a-token-session) examples on the right.
```bash Guardian theme={null}
curl --request POST \
--url https://.eu1.on-hellgate.cloud/api/pci/tokens \
--header 'content-type: application/json' \
--header 'authorization: Bearer ' \
--data '{ "source": "session" }'
```
```bash Commerce v2 theme={null}
curl --request POST \
--url https://sandbox.hellgate.io/tokens/session \
--header 'content-type: application/json' \
--header 'x-api-key: hlg-sbx-...'
```
```json Guardian theme={null}
{
"id": "a9f4e2c0-12d0-4b73-8e8c-0f0f0f0f0f0f",
"session_id": "7f2c9460-7e2e-403f-a08a-bc58cdcaea83",
"status": "pending"
}
```
```json Commerce v2 theme={null}
{
"session_id": "7f2c9460-7e2e-403f-a08a-bc58cdcaea83"
}
```
## Steps
Visit [https://demo.hellgate.dev/card](https://demo.hellgate.dev/card). The page loads the same Web SDK you would embed in your own application.
Use the **Backend Service URL** dropdown at the top of the page to match the environment that issued your session.
There are built-in options (e.g. **Sandbox (Shared Commerce v2)**), which target the Test tier of the shared Hellgate Commerce v2 platform.
For any other deployment — a dedicated Commerce v2 instance or a Guardian instance — enable the **Custom URL** toggle and enter the base URL of your backend (for example `https://.eu1.on-hellgate.cloud`).
Paste the `session_id` into the **Session ID** field.
The remaining controls change how the SDK renders the card form. Leave them at their defaults unless you want to preview a specific layout:
* **Schemes** — restrict the accepted card networks.
* **Card Layout** — render the card fields as **Single-line** or **Multi-line**.
* **Expiration Fields** — **Combined** month/year field or **Separate** fields.
* **Save my card** — toggles the `ephemeral` flag passed to `process()`, so you can exercise the [token lifecycle](/platform/resources/sdks/web-sdk/api#token-lifecycle) consent flow end-to-end.
Click **Test Card**, fill in the card details in the rendered form, and submit.
On success the workbench shows the resulting token. Confirm the same record through your own integration — for example by fetching it through the relevant product's API or viewing it in the Hellgate dashboard.
## Next steps
Once the workbench flow succeeds, port the same session-plus-SDK pattern into your own application:
* [Web SDK Overview](/platform/resources/sdks/web-sdk/overview) — initialize the SDK and render the card form.
* [Web SDK API](/platform/resources/sdks/web-sdk/api) — detailed handler and event reference.
# Create API key
Source: https://developer.hellgate.io/products/guardian/api-reference/apikey/create-api-key
/products/guardian/openapi.yaml post /api/admin/api-keys
Creates a new API key with the specified scopes and expiry defined via `expires_in` (seconds).
# Delete API key
Source: https://developer.hellgate.io/products/guardian/api-reference/apikey/delete-api-key
/products/guardian/openapi.yaml delete /api/admin/api-keys/{id}
Deletes a specific API key.
# Get API key details
Source: https://developer.hellgate.io/products/guardian/api-reference/apikey/get-api-key-details
/products/guardian/openapi.yaml get /api/admin/api-keys/{id}
Retrieves detailed information about a specific API key.
# Get API keys
Source: https://developer.hellgate.io/products/guardian/api-reference/apikey/get-api-keys
/products/guardian/openapi.yaml get /api/admin/api-keys
Retrieves a list of all API keys.
# Update API key
Source: https://developer.hellgate.io/products/guardian/api-reference/apikey/update-api-key
/products/guardian/openapi.yaml patch /api/admin/api-keys/{id}
Updates the scopes of an existing API key.
# Event notification
Source: https://developer.hellgate.io/products/guardian/api-reference/event-notification
/products/guardian/openapi.yaml webhook event_notification
This webhook is sent by the server to the client's registered URL when a subscribed event occurs.
# Create token
Source: https://developer.hellgate.io/products/guardian/api-reference/generic/create-token
/products/guardian/openapi.yaml post /api/generic/tokens
Create a new token in the generic scope. This type of token can be used for various use cases that do not involve sensitive card payment credentials.
# Delete a token
Source: https://developer.hellgate.io/products/guardian/api-reference/generic/delete-a-token
/products/guardian/openapi.yaml delete /api/generic/tokens/{id}
Remove a token from the system.
# Get token details
Source: https://developer.hellgate.io/products/guardian/api-reference/generic/get-token-details
/products/guardian/openapi.yaml get /api/generic/tokens/{id}
Get a token by its identifier.
# Get token payload
Source: https://developer.hellgate.io/products/guardian/api-reference/generic/get-token-payload
/products/guardian/openapi.yaml get /api/generic/tokens/{id}/payload
Retrieve the payload associated with a specific generic token.
# Get tokens
Source: https://developer.hellgate.io/products/guardian/api-reference/generic/get-tokens
/products/guardian/openapi.yaml get /api/generic/tokens
List all tokens in the generic scope.
# API Information
Source: https://developer.hellgate.io/products/guardian/api-reference/getting-started
Essential information for using the Guardian API
This reference is essential for your comprehensive understanding of Guardian and successful integration with our secure card data vault service.
Every endpoint on this reference, generated from the same OpenAPI specification and grouped exactly as the
navigation here. Duplicate the **Dedicated instance — template** environment and set `instance` and `env`.
The Authorization tab is pre-configured for the OAuth2 client-credentials grant, so add `clientId`,
`clientSecret`, `audiences` and `scopes` to the environment and hit **Get New Access Token**. Both
`audiences` and `scopes` are space-delimited lists — name every instance the token may call. See
[Authentication](/platform/authentication).
Guardian APIs make use of RESTful conventions when possible and where it makes sense. All calls use the standard HTTP verbs to express access semantics, like `GET`, `POST`, `PATCH`, and `DELETE`. Other related conventions for our API can be found in the section below.
## JSON Conventions
* Resources are addressable by a UUIDv4 `id` property.
* Property names are always in `snake_case`.
* Temporal data is encoded in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) strings.
### Empty Strings and Omitted Fields
The empty string is not a value. A string field is either **omitted** or present with a **real value** — and
where a field is nullable, an explicit `null` unsets it. Never send `""`.
Where a field is validated as a string, `""` is rejected with **422 Unprocessable Entity** and a field error
on that path (see [Request Errors](#request-errors) for the response format). Not every field carries that
validation, so do not treat the rejection as a safety net: where it is absent, `""` is accepted and then
stored or forwarded verbatim — an empty string travels further into a request than a missing field ever does.
## Authentication
Guardian authenticates every request with an **OAuth2 access token** — a signed JWT — passed as a bearer
token. Request the token with the client-credentials grant against the platform
[Authentication API](/platform/api-reference/overview); the token's audience is your instance name, and its
scopes gate the endpoints it may call.
```bash theme={null}
curl --header 'Authorization: Bearer ' \
--request POST 'https://my-instance.eu1.on-hellgate.cloud/api/...'
```
Administrative endpoints use the same token carrying the relevant `admin:*` scope. See
[Authentication](/products/guardian/authentication) for the full scope reference.
### API keys (deprecated)
Guardian still accepts a long-lived instance key in the `x-api-key` header, so existing integrations keep
working. New integrations should use an access token instead.
```bash theme={null}
curl --header 'x-api-key: ' \
--request POST 'https://my-instance.eu1.on-hellgate.cloud/api/...'
```
The `x-admin-token` header it used to pair with has been replaced by scoped access tokens.
Credentials must be handled with care and kept secure. Never hardcode tokens or API keys in your source code —
keep them solely on your backend systems.
## API Use
### Instance URL
Guardian is provided as a service of the Hellgate Cloud Platform implementing the [Composable Payment Architecture (CPA)](/platform/cpa). Each instance is accessible at a unique host:
```
https://{instance}.eu1.on-hellgate.cloud
```
`{instance}` is your unique instance slug and `eu1` is the current environment; both are provided during onboarding.
### Pagination
Endpoints that return lists of objects support pagination.
Guardian uses simple offset-based pagination with the following query parameters:
| Parameter | Type | Description |
| - | - | - |
| `limit` | `integer` | The maximum amount of objects to be returned per request. Default is 50. |
| `after` | `string` (uuid) | The id of the element from which on-wards the new list is determined. It is typically the last element from the previous list. |
Example request:
```bash theme={null}
curl --header 'Authorization: Bearer ' \
'https://my-instance.eu1.on-hellgate.cloud/api/pci/tokens?limit=25&after=08f4b968-259a-4989-b5ab-09ef9414f983'
```
The response includes pagination metadata:
```json theme={null}
{
"data": [...],
"links": {
"next": "https://my-instance.eu1.on-hellgate.cloud/api/pci/tokens?limit=25&after=605d229d-fc8a-4017-b115-2e606031bd79",
}
}
```
### Request Errors
Guardian uses standard HTTP status codes to indicate client errors on the API level.
The response payload for processing errors follows a standard format.
```json theme={null}
{
"status": "the HTTP status code",
"classifier": "the classifier of the error",
"message": "interesting for humans..."
}
```
The response payload for validation errors follows a standard
format which includes the validation errors.
```json theme={null}
{
"status": "the HTTP status code",
"classifier": "the classifier of the error",
"message": "interesting for humans...",
"validation_errors": [
{
"path": "a JSON path pointing to the wrong data",
"message": "something interesting for humans..."
}
]
}
```
### Security Considerations
Guardian handles sensitive payment card data and requires strict security practices:
* All communication must use HTTPS
* Access tokens, and any remaining API keys, must be stored securely
* PCI compliance requirements apply based on your integration approach
* Session-based tokenization (SAQ-A+) is recommended over direct PAN handling (SAQ-D+)
## Data Classification
Fields that carry regulated data are marked with a classification pill next to the parameter name in this
reference. The marker tells you what kind of data the field holds, so you can see at a glance which parts of a
payload attract handling obligations before you write any code against them.
| Marker | The field carries |
| - | - |
| pci-pan | The primary account number — a card number, or a value from which one can be reconstructed. |
| pci-sad | Sensitive authentication data — security codes and the equivalent authentication values issued for a token. |
| pii | Personal data under the GDPR — any information relating to an identified or identifiable person, not only the cardholder. |
Most fields carry no marker at all. The absence of one is a statement that the field holds none of the
categories above — not that the field has yet to be reviewed. Masked and truncated card numbers are the
common example: `411111 •••••• 1111` identifies nobody on its own, so it carries no marker.
The marker is also a gate, not just a label. Sending values into `pci-pan` or `pci-sad` fields requires your
PCI DSS certification on file at **SAQ-D** or a full Report on Compliance (RoC). Sending
[personal data](https://eur-lex.europa.eu/eli/reg/2016/679/oj) into `pii` fields requires a data processing
agreement (DPA) between us. Contact [support@hellgate.io](mailto:support@hellgate.io) to put either in place
or to learn more.
# Create inquiry
Source: https://developer.hellgate.io/products/guardian/api-reference/metadata/create-inquiry
/products/guardian/openapi.yaml post /api/metadata/inquiries
Create a new inquiry for card metadata based on either a PAN, an existing PCI token, or a network token.
# Create token
Source: https://developer.hellgate.io/products/guardian/api-reference/network/create-token
/products/guardian/openapi.yaml post /api/network/tokens
Create and provision a new network token with a card scheme. See [Network Tokens overview](/products/guardian/tokens/network-tokens) for creation sources and supported schemes.
Promoting a wallet token that was already promoted returns `422` with the classifier `WALLET_TOKEN_ALREADY_PROMOTED`; promoting a token that carries no funding PAN (a `CRYPTOGRAM_3DS` token) returns `422` with `UNSUPPORTED_WALLET_TYPE`. See [Promotion](/products/guardian/tokens/wallet-tokens/google-pay#promotion) for eligibility.
# Delete token
Source: https://developer.hellgate.io/products/guardian/api-reference/network/delete-token
/products/guardian/openapi.yaml delete /api/network/tokens/{id}
Deletes a specific network token by its ID.
# Forward cryptogram
Source: https://developer.hellgate.io/products/guardian/api-reference/network/forward-cryptogram
/products/guardian/openapi.yaml post /api/network/tokens/{id}/forward
Forward a request to a certified third-party provider with cryptogram data injected server-side, so it never touches your systems. This lets SAQ-A merchants use network tokens without ever handling a raw cryptogram, and mirrors [Forward card data](/products/guardian/api-reference/pci/forward-card-data).
- Resolves the single-use `x-cryptogram-reference` returned by [Request cryptogram](/products/guardian/api-reference/network/request-cryptogram) in `reference` mode.
- Injects the cryptogram and other PCI-scoped fields (token PAN, expiry, ECI, and more) into your request body via placeholders.
- Forwards the result to the `x-destination-url`.
See [Network Tokens](/products/guardian/tokens/network-tokens#forwarding-cryptograms) for the full placeholder list.
# Get card art
Source: https://developer.hellgate.io/products/guardian/api-reference/network/get-card-art
/products/guardian/openapi.yaml get /api/network/tokens/{id}/card-art
Get the card art associated with the network token.
# Get token details
Source: https://developer.hellgate.io/products/guardian/api-reference/network/get-token-details
/products/guardian/openapi.yaml get /api/network/tokens/{id}
Retrieves details of a specific network token by its ID.
# Get tokens
Source: https://developer.hellgate.io/products/guardian/api-reference/network/get-tokens
/products/guardian/openapi.yaml get /api/network/tokens
List all network tokens.
# Request cryptogram
Source: https://developer.hellgate.io/products/guardian/api-reference/network/request-cryptogram
/products/guardian/openapi.yaml post /api/network/tokens/{id}/cryptograms
Request a cryptogram (TAVV) for a network token. Supports `ecom` (e-commerce) and `dauth` (delegated authentication).
Set `mode` to control how the cryptogram is returned. `inline` returns the full cryptogram payload (SAQ-D / RoC only). `reference` returns a short-lived, single-use `cryptogram_reference` that you forward with [Forward cryptogram](/products/guardian/api-reference/network/forward-cryptogram). When omitted, `mode` defaults to `inline` on SAQ-D / RoC and is forced to `reference` on SAQ-A / SAQ-A EP. See [Network Tokens overview](/products/guardian/tokens/network-tokens).
# Check security code
Source: https://developer.hellgate.io/products/guardian/api-reference/pci/check-security-code
/products/guardian/openapi.yaml get /api/pci/tokens/{id}/security-code
Check if the security code is still available for the token.
# Create token
Source: https://developer.hellgate.io/products/guardian/api-reference/pci/create-token
/products/guardian/openapi.yaml post /api/pci/tokens
Create a new token in the PCI DSS scope. See [PCI Tokens overview](/products/guardian/tokens/pci-tokens) for creation sources (session vs pan) and compliance levels.
# Delete a token
Source: https://developer.hellgate.io/products/guardian/api-reference/pci/delete-a-token
/products/guardian/openapi.yaml delete /api/pci/tokens/{id}
Remove a token from the system.
# Delete security code
Source: https://developer.hellgate.io/products/guardian/api-reference/pci/delete-security-code
/products/guardian/openapi.yaml delete /api/pci/tokens/{id}/security-code
Remove the security code for the token.
# Forward card data
Source: https://developer.hellgate.io/products/guardian/api-reference/pci/forward-card-data
/products/guardian/openapi.yaml post /api/pci/tokens/{id}/forward
This endpoint allows to securely forward cardholder data to a certified third-party provider. It will inject sensitive cardholder data from the PCI token into the request before forwarding it.
# Get token details
Source: https://developer.hellgate.io/products/guardian/api-reference/pci/get-token-details
/products/guardian/openapi.yaml get /api/pci/tokens/{id}
Get a token by its identifier.
# Get tokens
Source: https://developer.hellgate.io/products/guardian/api-reference/pci/get-tokens
/products/guardian/openapi.yaml get /api/pci/tokens
List all tokens in the PCI DSS scope.
# Refresh security code
Source: https://developer.hellgate.io/products/guardian/api-reference/pci/refresh-security-code
/products/guardian/openapi.yaml post /api/pci/tokens/{id}/security-code
Request a refresh of the security code for the token.
# Create type
Source: https://developer.hellgate.io/products/guardian/api-reference/types/create-type
/products/guardian/openapi.yaml post /api/admin/types
Create a type on Guardian, which can be used to define a schema for generic tokens.
# Delete a type
Source: https://developer.hellgate.io/products/guardian/api-reference/types/delete-a-type
/products/guardian/openapi.yaml delete /api/admin/types/{id}
Remove a type from the system.
# Get type details
Source: https://developer.hellgate.io/products/guardian/api-reference/types/get-type-details
/products/guardian/openapi.yaml get /api/admin/types/{id}
Get a type by its identifier.
# Get types
Source: https://developer.hellgate.io/products/guardian/api-reference/types/get-types
/products/guardian/openapi.yaml get /api/admin/types
List all types.
# Create certificates
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/create-certificates
/products/guardian/openapi.yaml post /api/wallet/apple-pay/certificates
Generate the certificate signing requests (CSRs) Guardian needs for Apple Pay. Guardian creates both an EC **payment processing** CSR and an RSA **merchant identity** CSR and keeps the private keys inside its PCI boundary. Submit each `csr_pem` to Apple in the [Apple Developer](https://developer.apple.com/account/resources/certificates/list) portal, then return the signed certificates with [Upload an Apple Pay certificate](/products/guardian/api-reference/wallet/upload-a-certificate).
Available only on `self_managed` instances. On Starfish-operated (`sf_operated`) instances certificates are managed by Starfish, and this endpoint returns `409` with the classifier `APPLE_PAY_CERT_MANAGEMENT_UNAVAILABLE`.
# Delete a certificate
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/delete-a-certificate
/products/guardian/openapi.yaml delete /api/wallet/apple-pay/certificates/{id}
Delete an Apple Pay certificate. Only a terminal (`retired` or `disabled`) certificate can be deleted; deleting an `active` or `pending` certificate returns `409` with the classifier `CERTIFICATE_NOT_TERMINAL`.
# Delete a domain
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/delete-a-domain
/products/guardian/openapi.yaml delete /api/wallet/apple-pay/domains/{id}
Remove a domain from Apple Pay. The domain can no longer present the Apple Pay button until re-registered and verified.
# Delete a wallet token
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/delete-a-wallet-token
/products/guardian/openapi.yaml delete /api/wallet/{id}
Delete a wallet token. The stored card data is scrubbed immediately; the token record itself is kept with `deleted_at` set and is returned in the response. A deleted token can no longer be forwarded or promoted.
# Disable a certificate
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/disable-a-certificate
/products/guardian/openapi.yaml post /api/wallet/apple-pay/certificates/{id}/disable
Disable an active Apple Pay certificate so Guardian stops using it, without deleting the record.
# Forward wallet token
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/forward-wallet-token
/products/guardian/openapi.yaml post /api/wallet/{id}/forward
Forward a request to a certified third-party provider with the wallet token's card data injected server-side, so it never touches your systems. This mirrors [Forward card data](/products/guardian/api-reference/pci/forward-card-data) and [Forward cryptogram](/products/guardian/api-reference/network/forward-cryptogram).
The available placeholders depend on the token's `auth_method`:
- `CRYPTOGRAM_3DS`: `{{ dpan }}`, `{{ cryptogram }}`, `{{ eci }}`, `{{ expiry_month }}`, `{{ expiry_year }}`. The cryptogram is single-use — the token is consumed by the first successful forward.
- `PAN_ONLY`: `{{ fpan }}`, `{{ expiry_month }}`, `{{ expiry_year }}`. Forwardable repeatedly.
Using a placeholder the token's `auth_method` does not carry returns `422` with the classifier `DESTINATION_POLICY_VIOLATION`; a declared placeholder without a value on this specific token returns `422` with `PLACEHOLDER_VALUE_MISSING`. Forwarding an already-consumed `CRYPTOGRAM_3DS` token returns `400` with `CRYPTOGRAM_CONSUMED`.
See [Wallet Tokens](/products/guardian/tokens/wallet-tokens/overview#forwarding-wallet-tokens) for details.
# Get association file
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-association-file
/products/guardian/openapi.yaml get /.well-known/apple-developer-merchantid-domain-association.txt
Serve the Apple-issued domain-association file for this instance. This endpoint is public and unauthenticated: Apple fetches it while verifying a registered domain. Host it from every domain that presents the Apple Pay button. The same file is also served without the `.txt` extension, at `/.well-known/apple-developer-merchantid-domain-association`.
If no domain-association content is configured yet, the request returns `400` with the classifier `APPLE_PAY_NOT_CONFIGURED`.
# Get audit events
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-audit-events
/products/guardian/openapi.yaml get /api/wallet/apple-pay/certificates/{id}/audit-events
List the audit events recorded for an Apple Pay certificate, such as activation, retirement, and use.
# Get certificate details
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-certificate-details
/products/guardian/openapi.yaml get /api/wallet/apple-pay/certificates/{id}
Get an Apple Pay certificate by its identifier.
# Get certificates
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-certificates
/products/guardian/openapi.yaml get /api/wallet/apple-pay/certificates
List the Apple Pay payment processing certificates registered on this instance.
# Get domain details
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-domain-details
/products/guardian/openapi.yaml get /api/wallet/apple-pay/domains/{id}
Get an Apple Pay domain by its identifier.
# Get domains
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-domains
/products/guardian/openapi.yaml get /api/wallet/apple-pay/domains
List the domains registered for Apple Pay on this instance.
# Get settings
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-settings
/products/guardian/openapi.yaml get /api/wallet/apple-pay/settings
Return the operating `mode` of this instance, along with the settings uploaded via [Update settings](/products/guardian/api-reference/wallet/update-settings). All fields other than `mode` are `null` until the first upload, and always `null` on `sf_operated` instances, where the Apple identity is mounted by Starfish and not exposed through this endpoint.
# Get trust anchor
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-trust-anchor
/products/guardian/openapi.yaml get /api/wallet/apple-pay/trust-anchors
Return the active Apple Root CA trust anchor on this instance.
# Get wallet token details
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-wallet-token-details
/products/guardian/openapi.yaml get /api/wallet/{id}
Get a wallet token by its identifier.
# Get wallet tokens
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/get-wallet-tokens
/products/guardian/openapi.yaml get /api/wallet
List all wallet tokens.
# Register a domain
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/register-a-domain
/products/guardian/openapi.yaml post /api/wallet/apple-pay/domains
Register a domain that will present the Apple Pay button.
On `self_managed` instances the domain is marked `verified` immediately: you attest domain ownership to Apple yourself by registering the domain in the Apple Developer portal, where Apple fetches the domain-association file you serve at `/.well-known/apple-developer-merchantid-domain-association.txt`.
On `sf_operated` instances Guardian instead schedules a background verification that registers the domain with Apple's Web Merchant Registration API using the platform integrator identity, and the domain starts as `pending`. If the verification attempt cannot be scheduled, the request returns `503` with the classifier `ENQUEUE_FAILED`; retry the request.
# Replace trust anchor
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/replace-trust-anchor
/products/guardian/openapi.yaml post /api/wallet/apple-pay/trust-anchors
Replace the active Apple Root CA trust anchor Guardian verifies payment payloads against. The instance ships with Apple's current root CA seeded, so you only need this if Apple rotates its root certificate. The previous anchor is superseded atomically.
A PEM that cannot be decoded as a valid X.509 certificate returns `422` with the classifier `APPLE_PAY_INVALID_TRUST_ANCHOR`.
# Retire a certificate
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/retire-a-certificate
/products/guardian/openapi.yaml post /api/wallet/apple-pay/certificates/{id}/retire
Retire an Apple Pay certificate that is no longer in use, for example after rotating to a newer one.
# Tokenize Apple Pay
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/tokenize-apple-pay
/products/guardian/openapi.yaml post /api/wallet/apple-pay/tokenize
Turn an Apple Pay payment into a stored wallet token. Pass the `PKPaymentToken` `paymentData` envelope exactly as the Apple Pay JS API returns it, as the `payment_data` field. Guardian verifies the `EC_v1` signature against Apple's trusted certificates and decrypts the payload server-side with your active payment processing certificate, so the decrypted card data never touches your systems.
An Apple Pay payment always yields a device-bound token: a device PAN (DPAN) with a single-use cryptogram and ECI. The underlying funding PAN is never extracted, stored, or returned, so an Apple Pay token cannot be promoted to a network token.
Tokenization is idempotent on the encrypted payload: resubmitting the same envelope returns the existing wallet token. If that payload's token was already deleted, the request returns `409` with the classifier `APPLE_PAY_TOKEN_DELETED`. Rejected envelopes return `422` with a classifier naming the cause: `APPLE_PAY_SIGNATURE_INVALID`, `APPLE_PAY_UNKNOWN_CERTIFICATE`, `APPLE_PAY_TOKEN_EXPIRED`, or `APPLE_PAY_MALFORMED_TOKEN` (Guardian's generic missing-field classifier, shared by the other Apple Pay endpoints). If no active payment processing certificate exists, the request returns `500` with the classifier `APPLE_PAY_NO_ACTIVE_CERTIFICATE`.
See [Apple Pay](/products/guardian/tokens/wallet-tokens/apple-pay) for prerequisites and the full flow.
# Tokenize Google Pay
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/tokenize-google-pay
/products/guardian/openapi.yaml post /api/wallet/google-pay/tokenize
Turn a Google Pay payment into a stored wallet token. Pass the `PaymentMethodToken` envelope exactly as Google Pay returns it — Guardian verifies the ECv2 signature chain and decrypts the payload server-side, so the decrypted card data never touches your systems.
The resulting wallet token carries one of two authentication methods, reflected in the `auth_method` field:
- `CRYPTOGRAM_3DS` — a device-bound token with DPAN and cryptogram, forwardable once.
- `PAN_ONLY` — a card-on-file token with the funding PAN, forwardable repeatedly and eligible for [promotion to a network token](/products/guardian/tokens/wallet-tokens/google-pay#promotion).
Submitting the same envelope twice returns `409` with the classifier `GOOGLE_PAY_DUPLICATE_PAYLOAD`. Rejected envelopes return `422` with a classifier naming the cause: `GOOGLE_PAY_SIGNATURE_INVALID`, `GOOGLE_PAY_DECRYPTION_FAILED`, `GOOGLE_PAY_TOKEN_EXPIRED`, or `GOOGLE_PAY_MALFORMED_TOKEN`.
See [Google Pay](/products/guardian/tokens/wallet-tokens/google-pay) for prerequisites and the full flow.
# Update settings
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/update-settings
/products/guardian/openapi.yaml put /api/wallet/apple-pay/settings
Upload your Apple identity so Guardian can generate CSRs, serve the domain-association file, and validate merchant sessions. Provide your `merchant_identifier`, a `display_name`, the byte-exact `domain_association_content` Apple issued, and the `csr_common_name` to embed in generated CSRs.
The upload is a partial update: fields you omit keep their current values, and no field is individually required. All four must be set before the dependent flows work.
Available only on `self_managed` instances. On Starfish-operated (`sf_operated`) instances the Apple identity and certificates are managed by Starfish, and this endpoint returns `409` with the classifier `APPLE_PAY_CERT_MANAGEMENT_UNAVAILABLE`.
# Upload a certificate
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/upload-a-certificate
/products/guardian/openapi.yaml post /api/wallet/apple-pay/certificates/{id}/upload
Return the signed certificate chain Apple issued for a CSR created with [Create Apple Pay certificates](/products/guardian/api-reference/wallet/create-certificates). Once uploaded, the certificate moves to `active` and becomes the one Guardian uses to decrypt payloads and authenticate to Apple.
# Validate Apple Pay session
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/validate-apple-pay-session
/products/guardian/openapi.yaml post /api/wallet/apple-pay/sessions
Complete Apple Pay's `onvalidatemerchant` exchange. When the customer opens the Apple Pay sheet in a browser, Apple fires `onvalidatemerchant`; your backend forwards the request here. Guardian performs the mTLS handshake with Apple using your merchant identity certificate and returns Apple's merchant session object verbatim, which you pass to `session.completeMerchantValidation(...)` in the browser.
The `domain_name` must be a verified [Apple Pay domain](/products/guardian/tokens/wallet-tokens/apple-pay#prerequisites). Guardian reads your merchant identifier and display name from the [Apple Pay settings](/products/guardian/api-reference/wallet/get-settings); until those are uploaded the request returns `400` with the classifier `APPLE_PAY_NOT_CONFIGURED`. A request for an unregistered or unverified domain returns `422` with the classifier `APPLE_PAY_DOMAIN_NOT_VERIFIED`. If Apple rejects the validation, Guardian returns `502` with `APPLE_PAY_SESSION_ERROR`; if no active merchant identity certificate exists, the request returns `500` with `APPLE_PAY_NO_ACTIVE_CERTIFICATE`.
# Verify a domain
Source: https://developer.hellgate.io/products/guardian/api-reference/wallet/verify-a-domain
/products/guardian/openapi.yaml post /api/wallet/apple-pay/domains/{id}/verify
Re-verify a `pending` or `failed` domain, for example a row created before a mode switch or a failed `sf_operated` attempt. A domain that is already `verified` returns `409` with the classifier `DOMAIN_NOT_RETRIABLE`.
On `self_managed` instances the domain is marked `verified` immediately, trusting your own attestation of domain ownership to Apple. On `sf_operated` instances Guardian schedules a background verification against Apple's Web Merchant Registration API using the platform integrator identity; if the attempt cannot be scheduled, the request returns `503` with the classifier `ENQUEUE_FAILED`.
# Delete webhook
Source: https://developer.hellgate.io/products/guardian/api-reference/webhook/delete-webhook
/products/guardian/openapi.yaml delete /api/admin/webhooks/{id}
Deletes a specific webhook.
# Get webhook details
Source: https://developer.hellgate.io/products/guardian/api-reference/webhook/get-webhook-details
/products/guardian/openapi.yaml get /api/admin/webhooks/{id}
Retrieves detailed information about a specific webhook.
# Get webhooks
Source: https://developer.hellgate.io/products/guardian/api-reference/webhook/get-webhooks
/products/guardian/openapi.yaml get /api/admin/webhooks
List all webhooks known to the system.
# Register webhook
Source: https://developer.hellgate.io/products/guardian/api-reference/webhook/register-webhook
/products/guardian/openapi.yaml post /api/admin/webhooks
Register a new webhook and receive callbacks.
# Authentication
Source: https://developer.hellgate.io/products/guardian/authentication
Authenticate to your Guardian instance with an OAuth2 access token and the scopes that gate each endpoint.
Once your Guardian instance is provisioned (see [Plans & Access](/products/guardian/plans-and-access)), you
reach the API at your dedicated instance URL, where `{instance}` is your unique instance slug and `eu1` is the
current environment; both are provided during onboarding:
```
https://{instance}.eu1.on-hellgate.cloud
```
## Authentication
Every API request must carry an OAuth2 access token — a signed JSON Web Token (JWT) — in the
`Authorization` header:
```http theme={null}
Authorization: Bearer
```
You request the token with the client-credentials grant — see [Authentication](/platform/authentication) for
the token endpoint, audiences, and scopes. Your instance's audience is its instance name.
**API keys are deprecated.** Guardian still accepts a long-lived instance key in the `x-api-key` header, so
existing integrations keep working, but new integrations should use an access token. The `x-admin-token`
header has been replaced — administrative endpoints now use the same access token carrying the relevant
`admin:*` scope.
## Scopes
Each endpoint requires a specific scope. Request only the scopes a given integration needs through the
`scope` parameter when you [request a token](/platform/authentication) — follow the principle of least
privilege.
### Token operations
| Scope | Grants |
| - | - |
| `pci:tokens:create` | `POST /api/pci/tokens` |
| `pci:tokens:read` | `GET /api/pci/tokens` `GET /api/pci/tokens/{id}` `GET /api/pci/tokens/{id}/security-code` |
| `pci:tokens:update` | `POST /api/pci/tokens/{id}/security-code` `DELETE /api/pci/tokens/{id}/security-code` |
| `pci:tokens:delete` | `DELETE /api/pci/tokens/{id}` |
| `pci:tokens:forward` | `POST /api/pci/tokens/{id}/forward` |
| `generic:tokens:create` | `POST /api/generic/tokens` |
| `generic:tokens:read` | `GET /api/generic/tokens` `GET /api/generic/tokens/{id}` `GET /api/generic/tokens/{id}/payload` |
| `generic:tokens:delete` | `DELETE /api/generic/tokens/{id}` |
| `network:tokens:create` | `POST /api/network/tokens` |
| `network:tokens:read` | `GET /api/network/tokens` `GET /api/network/tokens/{id}` `GET /api/network/tokens/{id}/card-art` |
| `network:tokens:delete` | `DELETE /api/network/tokens/{id}` |
| `network:tokens:use` | `POST /api/network/tokens/{id}/cryptograms` |
| `network:tokens:forward` | `POST /api/network/tokens/{id}/forward` |
| `metadata:inquiries:create` | `POST /api/metadata/inquiries` |
`network:tokens:*` requires the **Network Tokens** add-on, and `metadata:inquiries:create` requires the
**Metadata Inquiries** add-on, enabled on your instance. See [Plans & Access](/products/guardian/plans-and-access).
### Administrative operations
Administrative endpoints manage the instance itself. They require a token carrying the relevant `admin:*`
scope, and should be issued to operator or back-office clients only.
| Scope | Grants |
| - | - |
| `admin:api-keys:create` | `POST /api/admin/api-keys` |
| `admin:api-keys:read` | `GET /api/admin/api-keys` `GET /api/admin/api-keys/{id}` |
| `admin:api-keys:update` | `PATCH /api/admin/api-keys/{id}` |
| `admin:api-keys:delete` | `DELETE /api/admin/api-keys/{id}` |
| `admin:webhooks:create` | `POST /api/admin/webhooks` |
| `admin:webhooks:read` | `GET /api/admin/webhooks` `GET /api/admin/webhooks/{id}` |
| `admin:webhooks:delete` | `DELETE /api/admin/webhooks/{id}` |
| `admin:types:create` | `POST /api/admin/types` |
| `admin:types:read` | `GET /api/admin/types` `GET /api/admin/types/{id}` |
| `admin:types:delete` | `DELETE /api/admin/types/{id}` |
| `admin:imports:create` | `POST /api/admin/imports` |
| `admin:imports:read` | `GET /api/admin/imports/{id}` |
| `admin:imports:cancel` | `POST /api/admin/imports/{id}/cancel` |
## Next steps
Manage the deprecated instance API keys that existing integrations still use.
# Guardian Updates
Source: https://developer.hellgate.io/products/guardian/changelog
New releases and improvements of Guardian.
## Masked Token Number and PAR on Network Tokens
The network token object now carries the masked token number (TPAN) and the
Payment Account Reference: `network_token.masked_number`, `last_four`, `bin`
and `payment_account_reference`. Guardian derives them from the token data it
already sees at provisioning and on the cryptogram path and stores only the
BIN, the last four digits and the PAR; the plaintext TPAN still never
leaves the card data environment. Tokens provisioned before this release
receive the digits with their next cryptogram, Mastercard tokens their PAR
through a backfill; each change is announced by a `network.token.updated`
webhook.
[List tokens](/products/guardian/api-reference/network/get-tokens) accepts a
`last_four` filter, the first filter on that endpoint, and keeps it in the
pagination links. The admin token lookup shows the masked number and the PAR.
See [Token Digits and PAR](/products/guardian/tokens/network-tokens#token-digits-and-par).
## Bugfixes
* Forwards to a destination whose hostname is an alias (a DNS `CNAME`) are
delivered again. Since the September 30 release, such forwards failed with
a `500`.
## Scheme Deletions Delete the Network Token
A network token the card scheme deletes is now deleted in Guardian exactly
like one you delete through the API: it disappears from the token list and
can no longer be read. Until now a scheme-side deletion only set the status
to `deleted`, so the token stayed listed and you learned about it through a
`network.token.updated` webhook. Both kinds of deletion now send a dedicated
`network.token.deleted` webhook, so you no longer have to infer a deletion
from a status change.
## Forwards Go Only Where They Were Checked
Guardian resolves a forward's destination once, checks that address, and
sends the request to exactly that address. A hostname can no longer pass the
check with a public address and then resolve to an internal one when the
request is sent. The destination still receives its own hostname in the
`Host` header, with the port when it is not the default, including
destinations reachable only over IPv6.
## Improvements and bugfixes
* A custom header pair (`x-own-header-name` / `x-own-header-value`) can no
longer set `Host` or `Content-Length`. Guardian sets both itself and drops
a pair that names either.
* A card number in `metadata` or `additional_data`, for example in
`cardholder_name`, is rejected on every tier, test cards included.
* Endpoints that never take card data — such as sessions, forwards, and
generic tokens — reject a request that carries a card number in any field,
including a card number sent as an unquoted JSON number or as a query
parameter.
## Forwards Are Delivered at Most Once
Forwarding — card data, cryptogram, or wallet token — now guarantees
at-most-once delivery to your destination. Guardian never retries a forward
on its own: a payment authorization cannot reach your endpoint twice, and a
failed forward is always yours to decide about. At the same time, the
sporadic `502` responses some integrations saw when a pooled connection to
the destination had gone stale are gone — Guardian discards idle
connections before that can happen, so the fresh guarantee does not come at
the cost of more transient errors.
## Improvements and bugfixes
* A session created with `expires_in` now strictly caps the resulting
token's lifetime. Lifecycle arguments in the encrypted client payload —
documented as ignored on such sessions — could previously extend a
token's expiry past the session's TTL; they no longer can. See
[PCI Tokens](/products/guardian/tokens/pci-tokens) for how session and
client-side lifecycle settings interact.
* Browser requests to the session endpoints now accept the Web SDK's
traceability headers, so cross-origin session calls carry full request
tracing.
## Forward Header Overrides and PCI Token Expiry in the Specification
The OpenAPI document now declares the `x-own-header-name` / `x-own-header-value`
header pair on all three forward operations — card data, cryptogram, and wallet
token. Guardian strips the credential your call authenticates with before
forwarding; the pair sets the destination's own credential on the forwarded
request. The behavior is unchanged and was already described in the
[PCI Tokens guide](/products/guardian/tokens/pci-tokens#http-headers); clients
generated from the document alone could not send a destination credential
before.
`pci_token.expires_at` is now typed nullable: a token created without an expiry
returns `"expires_at": null`, which a schema-validating client previously had
to reject.
Documentation only; no endpoint changed. Regenerate clients.
## Data Classification Markers on Card Fields
The Guardian API reference now marks every field that carries regulated data.
`account_number` and the PAN returned on a cryptogram are marked `pci-pan`;
`security_code`, the cryptogram itself, and the dynamic CVV are marked
`pci-sad`; `cardholder_name` is marked `pii`.
The marker is a gate as well as a label: sending values into `pci-pan` or
`pci-sad` fields requires your PCI DSS certification on file at SAQ-D or a full
Report on Compliance. This is what makes the difference between the
session-based and direct-PAN integration paths visible field by field.
Fields without a marker hold none of those categories — masked and truncated
card numbers are the common example. The
[full legend](/products/guardian/api-reference/getting-started#data-classification)
is on the API reference.
Nothing about any endpoint changed — this is documentation only.
## Polymorphic Request Bodies Specified as Discriminated Unions
The request bodies that accept several shapes — `source` on PCI token creation,
network token creation, and metadata inquiry, plus the cryptogram request — are
now specified as discriminated unions on `type`. The accepted requests are
unchanged; what changes is that the specification states which `type` selects
which shape, so the reference documentation shows one tab per source and
generated clients get a proper tagged union.
Three places where the specification was looser than the API and has been
corrected: `type` is required on the cryptogram request, and both `type` and
`account_number` are required on a metadata inquiry from a PAN. Requests
missing them were already rejected — the document simply did not say so.
Responses that vary by shape rather than by a tag — PCI token creation, network
token creation, and the cryptogram response — keep their existing structure and
now document how to tell the variants apart.
## Richer Network Token Provisioning Events
`network_token.provisioned` events now carry the `network_token_id`, the
`pci_token_id`, and the card's `last_four`, so you can reconcile provisioning
activity against your token records without extra lookups.
## Improvements and bugfixes
* Fixed access token verification: a valid OAuth2 access token could be
rejected with `401 invalid_token`. See
[Authentication](/products/guardian/authentication).
## OAuth2 Access Tokens Replace API Keys
Guardian now authenticates with an OAuth2 access token, the same
client-credentials flow used across the Hellgate Cloud Platform. Request a
token from the [Authentication API](/platform/api-reference/overview) with
your instance name as the audience, and send it as
`Authorization: Bearer `. The scopes that previously sat on an
API key now travel in the token.
Long-lived `x-api-key` credentials are **deprecated**. Existing integrations
keep working, but new ones should use access tokens. The `x-admin-token`
header has been replaced — administrative endpoints now accept the same
access token carrying the relevant `admin:*` scope. See
[Authentication](/products/guardian/authentication).
## Card Fingerprints on PCI Tokens
PCI token responses can now include `card.fingerprint`: a deterministic,
non-reversible identifier of the card number, unique per Guardian instance.
The same card always produces the same fingerprint — across `session` and
`pan` tokenization and after a reissue with a new expiry date — so you can
recognize a returning card without handling the PAN. The field is read-only
and enabled per instance. See
[PCI Tokens](/products/guardian/tokens/pci-tokens#card-fingerprints) for
details.
## Simpler Apple Pay Domain Verification on Self-Managed Deployments
On `self_managed` deployments, registering an Apple Pay domain now marks it
`verified` immediately: you attest domain ownership to Apple yourself by
registering the domain in the Apple Developer portal, where Apple fetches the
domain-association file you serve. Guardian no longer calls Apple during
registration on these deployments; only `sf_operated` deployments verify
domains against Apple's Web Merchant Registration API in the background. See
[Apple Pay](/products/guardian/tokens/wallet-tokens/apple-pay#prerequisites)
for the updated flow.
## Apple Pay Operating Modes and Settings
Guardian Apple Pay deployments now run in one of two modes. In `self_managed`
mode (the default) you upload your own Apple identity and manage the
certificates yourself; in `sf_operated` mode Starfish operates the Apple
Developer relationship and mounts the identity and certificates for you, so
the settings-upload and certificate-management endpoints are disabled and
return `409` with the classifier `APPLE_PAY_CERT_MANAGEMENT_UNAVAILABLE`.
Self-managed operators upload their Apple identity up front with the new
[Update settings](/products/guardian/api-reference/wallet/update-settings)
endpoint (`merchant_identifier`, `display_name`, `domain_association_content`,
and `csr_common_name`), which Guardian reads when generating CSRs, serving the
domain-association file, and validating merchant sessions. See
[Apple Pay](/products/guardian/tokens/wallet-tokens/apple-pay) for the full
setup.
## Wallet Tokens with Apple Pay
Guardian now accepts Apple Pay payments as wallet tokens. Pass the encrypted
`PKPaymentToken` payload straight to Guardian, and it verifies the `EC_v1`
signature against Apple's trusted certificates, decrypts, and stores the
device token server-side, so the decrypted card data never touches your
systems. Guardian also proxies Apple Pay merchant-session validation, so the
browser's `onvalidatemerchant` exchange completes without you holding any
Apple certificates. From there you can forward the resulting
[wallet token](/products/guardian/tokens/wallet-tokens/overview) to your PSP
or acquirer. See [Apple Pay](/products/guardian/tokens/wallet-tokens/apple-pay)
to get started.
## Apple Pay Certificate and Domain Management
Guardian now manages the credentials Apple Pay needs: it generates payment
processing and merchant identity CSRs with the private keys held inside its
PCI boundary, accepts the certificates Apple signs, tracks their lifecycle
(`pending`, `active`, `retired`, `disabled`) with per-certificate audit
events, and registers and verifies the merchant domains that present the
Apple Pay button. See
[Apple Pay](/products/guardian/tokens/wallet-tokens/apple-pay#prerequisites)
for the setup steps.
## Wallet Tokens with Google Pay
Guardian now accepts device wallet payments, starting with **Google Pay**.
Pass the encrypted Google Pay payload straight to Guardian — it verifies the
ECv2 signature chain, decrypts, and stores the credential server-side, so the
decrypted card data never touches your systems. From there you can forward the
resulting [wallet token](/products/guardian/tokens/wallet-tokens/overview) to your PSP
or acquirer, and promote a card-on-file (`PAN_ONLY`) token to a full network
token. See [Google Pay](/products/guardian/tokens/wallet-tokens/google-pay)
to get started.
## JWT Authentication
A new JWT authentication lane runs in parallel to API keys. Guardian validates
incoming tokens against your JWKS endpoint, letting you authenticate services
with short-lived JWTs instead of, or alongside, long-lived API keys.
## Network Token Cryptogram Forwarding
You can now forward a network token cryptogram by reference on
`POST /api/network/tokens/{id}/forward`, so Guardian resolves the cryptogram
server-side and it never touches your systems. Forward templates also expose
more binds — including `dynamic_cvv` and additional network token fields — for
richer downstream requests.
## Token Lifecycle Controls
New token lifecycle controls let you set and manage expiration on stored
tokens. Guardian accepts an `expiration_time` alias for `expires_in`, and a
session's `expires_in` now consistently takes precedence over the ephemeral
payload flag.
## Improvements and bugfixes
* Guardian now detects PANs in non-PAN attributes, catching card data that
would otherwise slip through in the wrong field.
* Ingress forwarding headers are no longer relayed to destinations, keeping
internal routing headers out of your outbound proxy requests.
* Network token create responses now serialize `pci_token_id`.
* Clearer proxy template errors: Guardian returns `422` when a placeholder
resolves to a map, validates unwrap placeholders inside multi-part
templates, and gives more precise messages for non-renderable placeholders.
* Ephemeral sessions without an `expires_in` are handled correctly.
## Guardian Admin UI
Guardian now ships with a built-in Admin UI for day-to-day token operations.
Browse and manage tokens, handle API keys with proper timezone-aware
expiration, and walk new operators through token creation — all backed by a
Playwright end-to-end test suite so it stays solid release after release.
## Metadata Inquiry Endpoint
A new `POST /metadata/inquiry` endpoint lets you look up issuer metadata
on-demand. The endpoint is feature-flagged per tier, propagates the
`x-request-id` end-to-end as a correlation ID, and emits a billing event
tagged with the requester's contract ID — so reporting and chargeback
reconciliation work out of the box.
## Improvements and bugfixes
* American Express now renders with its proper scheme name in admin views.
* Metadata inquiry events include `network_token_id` for richer
reconciliation data.
* Hellgate SDK `