ShieldConex WebSockets API
Overview
Tokenize, read, and detokenize data from your server through the ShieldConex WebSocket application programming interface (API).
WebSocket supports two-way communication over a persistent connection. Send requests and receive responses in JavaScript Object Notation (JSON) format.
Key Points
- Connect from your backend server, not a frontend client, to keep authentication credentials on your server.
- Authenticate the initial WebSocket connection using Basic authentication.
- Send a heartbeat message at least once every 5 seconds to keep the connection alive and check that the service is responding.
Connection Details
Connect to the URL for your ShieldConex environment in the table below. Include an Authorization header in the initial connection, as described in Basic authentication:
- Join your
partnerIdandpartnerKeywith a colon:partnerId:partnerKey. - Base64-encode the resulting string without adding a newline.
- Set the header to
Authorization: Basicfollowed by the encoded value.
Keep your credentials and the encoded header value on your server. Base64 encoding does not encrypt credentials. The Python examples below build the header at runtime without displaying it.
| Environment Name | WebSocket Connection URL |
|---|---|
| Staging Environment | wss://secure-staging-ws.shieldconex.com |
| Certification/Testing Environment | wss://secure-cert-ws.shieldconex.com |
| Production Environment | wss://secure-ws.shieldconex.com |
Request Message Structure
Request JSON messages have the following properties:
| Property | Required | Type | Length | Description |
|---|---|---|---|---|
| traceId | Yes | String | 0-255 | Choose a unique request identifier. ShieldConex returns the same traceId so you can match each response to its request.Use a globally unique identifier (GUID) to reduce collisions. |
| action | Yes | Enumeration | - | Choose the action to perform:heartbeatpartner-validatetemplate-validatetokenization-tokenizetokenization-readtokenization-detokenize |
| payload | Yes, except for heartbeat | JSON | - | Provide the fields for your chosen action. The heartbeat example omits payload.See the action-specific request and response examples below. |
Response Message Structure
Response JSON messages have the following properties:
| Property | Description |
|---|---|
| traceId | Matches the traceId you sent in the request. |
| action | Identifies the action ShieldConex performed. |
| messageId | Identifies the transaction. Use this system-generated value to track the message in the portal. |
| success | Reports whether ShieldConex processed the message successfully. |
| payload | Contains the action result when present. Tokenization failures include errorCode and message fields corresponding to the same action's REST (Representational State Transfer) endpoint. The validation examples below return only success. |
Tokenization responses include a Bluefin identifier (BFID) in payload.bfid. Keep this identifier to associate later read or detokenization requests with the original tokenization request.
Sample Messages
The JSON examples show message structure. Card numbers, tokens, and BFIDs use explicit redactions rather than usable values. Do not send these redactions in requests; use approved test data and values from your own test transactions.
{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e49",
"action": "tokenization-tokenize",
"payload": {
"templateRef": "8e1580b8-12ea-4804-acaa-f9c922d124e6",
"omit": false,
"reference": "09420c55af7b",
"values": [{
"name": "scx_token_card_number",
"value": "[redacted card number]"
}]
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e49",
"action": "tokenization-tokenize",
"messageId": "1201911201201321031626749",
"success": true,
"payload": {
"bfid": "[redacted BFID]",
"values": [{
"name": "scx_token_card_number",
"value": "[redacted token]"
}]
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e49",
"action": "tokenization-tokenize",
"messageId": "1201911201201321031626749",
"success": false,
"payload": {
"errorCode": 1202,
"message": "Template not found"
}
}Sample Code
Use this Python example to send a tokenization request without embedding credentials or card data in source code or logs.
- Install the WebSocket library:
python -m pip install websockets. - Select a template in your certification environment and copy its
templateReffrom ShieldConex Manager. - Save the code as
scx_action.pyand runpython scx_action.pyfrom an interactive server terminal. Enter your partner credentials and approved test values at the hidden prompts. Enter field names that match your template, and press Enter at the next field-name prompt when you have finished.
The script uses omit: false and store: true, so the response contains tokens and supports a later tokenization read. It keeps response values in memory instead of printing them. For long-lived connections, see the heartbeat implementation example.
import asyncio
import base64
import getpass
import json
import uuid
from websockets.exceptions import ConnectionClosed, InvalidHandshake
from websockets.legacy.client import connect
ENV_URL = "wss://secure-cert-ws.shieldconex.com"
async def scx_action():
partner_id = getpass.getpass("Partner ID: ")
partner_key = getpass.getpass("Partner key: ")
template_ref = input("Template reference: ").strip()
if not partner_id or not partner_key or not template_ref:
print("Enter both credentials and a template reference.")
return
values = []
while True:
name = input("Template field name (Enter to finish): ").strip()
if not name:
break
value = getpass.getpass("Approved test value: ")
if not value:
print("Enter a nonempty test value.")
return
values.append({"name": name, "value": value})
if not values:
print("Enter at least one template field.")
return
encoded = base64.b64encode(
f"{partner_id}:{partner_key}".encode("utf-8")
).decode("ascii")
headers = {"Authorization": f"Basic {encoded}"}
trace_id = str(uuid.uuid4())
request = {
"traceId": trace_id,
"action": "tokenization-tokenize",
"payload": {
"templateRef": template_ref,
"omit": False,
"store": True,
"reference": uuid.uuid4().hex[:12],
"values": values,
},
}
try:
async with connect(ENV_URL, extra_headers=headers) as websocket:
await websocket.send(json.dumps(request))
response = json.loads(
await asyncio.wait_for(websocket.recv(), timeout=10)
)
if not isinstance(response, dict):
print("Unexpected response: expected a JSON object.")
return
if (response.get("traceId") != trace_id
or response.get("action") != request["action"]):
print("Unexpected response: request identifiers do not match.")
return
payload = response.get("payload")
if response.get("success") is False:
error_code = payload.get("errorCode") if isinstance(payload, dict) else None
if error_code == 1202:
print("Tokenization failed: template not found. Check the template reference.")
else:
print("Tokenization failed. Inspect the response securely for error details.")
return
if response.get("success") is not True or not isinstance(payload, dict):
print("Unexpected response: missing success status or payload.")
return
if not payload.get("bfid") or not isinstance(payload.get("values"), list) or not payload["values"]:
print("Unexpected response: missing BFID or tokenized values.")
return
# Keep values out of logs; pass them directly to your server-side workflow.
print("Tokenization succeeded; BFID and tokenized values received (not displayed).")
except asyncio.TimeoutError:
print("No response within the example's 10-second timeout.")
except (json.JSONDecodeError, UnicodeDecodeError):
print("The server returned an invalid JSON response.")
except (OSError, ConnectionClosed, InvalidHandshake):
print("Connection failed or closed. Check the environment, credentials, and network.")
if __name__ == "__main__":
try:
asyncio.run(scx_action())
except (KeyboardInterrupt, EOFError):
print("Stopped.")Expected output after a successful request:
Tokenization succeeded; BFID and tokenized values received (not displayed).If ShieldConex returns error 1202, check that the template exists in the selected environment. For a failed connection, check your environment URL and Basic authentication credentials. The 10-second receive timeout is an example client setting, not a service limit.
Actions
Use the following actions to check connectivity, validate templates, and process data.
Heartbeat
Send a heartbeat action after the initial WebSocket handshake to check that ShieldConex is responding. ShieldConex returns a JSON response containing a timestamp when it receives your request. This application-level heartbeat is distinct from WebSocket protocol ping and pong frames.
{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e48",
"action": "heartbeat"
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e48",
"action": "heartbeat",
"messageId": "1202203181024092211390455",
"success": true,
"payload": {
"timestamp": 1647599049551
}
}Send a heartbeat message at least once every 5 seconds to keep the connection alive and check that the service is responding.
Heartbeat Server-Side Implementation
Use this standalone Python example to send a heartbeat every 5 seconds on one connection. Install websockets as described in Sample Code, save the code as heartbeat_check.py, and run python heartbeat_check.py. Enter your partner credentials at the hidden prompts; press Ctrl+C to stop.
A heartbeat checks only the connection that carries it. When you add tokenization, detokenization, or tokenization read actions to a persistent connection, use one receive loop and match responses to pending requests by traceId. Do not run concurrent recv() calls on the same connection.
import asyncio
import base64
import getpass
import json
import uuid
from websockets.exceptions import ConnectionClosed, InvalidHandshake
from websockets.legacy.client import connect
ENV_URL = "wss://secure-cert-ws.shieldconex.com"
async def heartbeat_check():
partner_id = getpass.getpass("Partner ID: ")
partner_key = getpass.getpass("Partner key: ")
if not partner_id or not partner_key:
print("Enter both partner credentials.")
return
encoded = base64.b64encode(
f"{partner_id}:{partner_key}".encode("utf-8")
).decode("ascii")
headers = {"Authorization": f"Basic {encoded}"}
try:
async with connect(ENV_URL, extra_headers=headers) as websocket:
loop = asyncio.get_running_loop()
while True:
started = loop.time()
trace_id = str(uuid.uuid4())
request = {"traceId": trace_id, "action": "heartbeat"}
await websocket.send(json.dumps(request))
response = json.loads(
await asyncio.wait_for(websocket.recv(), timeout=5)
)
if not isinstance(response, dict):
print("Unexpected heartbeat response: expected a JSON object.")
return
if (response.get("traceId") != trace_id
or response.get("action") != "heartbeat"):
print("Unexpected heartbeat response: request identifiers do not match.")
return
if response.get("success") is False:
print("Heartbeat failed. Inspect the response securely for error details.")
return
payload = response.get("payload")
if (response.get("success") is not True
or not isinstance(payload, dict)
or "timestamp" not in payload):
print("Unexpected heartbeat response: missing success status or timestamp.")
return
print("Heartbeat succeeded.")
# Include response time in the interval between heartbeat requests.
await asyncio.sleep(max(0, 5 - (loop.time() - started)))
except asyncio.TimeoutError:
print("No heartbeat response within the example's 5-second timeout.")
except (json.JSONDecodeError, UnicodeDecodeError):
print("The server returned an invalid JSON response.")
except (OSError, ConnectionClosed, InvalidHandshake):
print("Connection failed or closed. Check the environment, credentials, and network.")
if __name__ == "__main__":
try:
asyncio.run(heartbeat_check())
except (KeyboardInterrupt, EOFError):
print("Stopped.")Expected output repeats while ShieldConex responds:
Heartbeat succeeded.The example stops after a failure or timeout. Check the environment, credentials, and network before reconnecting. The 5-second receive timeout is a client setting for this example, not a documented service limit.
Partner Validate
Send partner-validate to test connectivity to ShieldConex with your partner credentials. ShieldConex returns success: true when validation succeeds.
The payload object contains the following field:
| Property | Required | Type | Length | Description |
|---|---|---|---|---|
| reference | No | String | 1–255 | Your reference for tracking requests and responses. This value serves only a tracking purpose. |
{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e48",
"action": "partner-validate",
"payload": {
"reference": "myref"
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e48",
"action": "partner-validate",
"messageId": "1201911201201321031626749",
"success": true
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e48",
"action": "partner-validate",
"messageId": "1201911201201321031626749",
"success": false
}Template Validate
Send template-validate to check that ShieldConex recognizes your partner's template and its configuration.
The payload object contains the following fields:
| Property | Required | Type | Length | Description |
|---|---|---|---|---|
| reference | No | String | 1–255 | Your reference for tracking requests and responses. This value serves only a tracking purpose. |
| templateRef | Yes | String | 1–255 | The unique identifier of the template to validate. |
{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e47",
"action": "template-validate",
"payload": {
"reference": "myref",
"templateRef": "152a4e3f7f31f0a746388adbae1b47f5"
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e47",
"action": "template-validate",
"messageId": "1201911201201321031626749",
"success": true
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e47",
"action": "template-validate",
"messageId": "1201911201201321031626749",
"success": false
}Tokenize
Send tokenization-tokenize to replace data with tokens using your template's field configuration.
The payload object contains the following fields:
| Property | Required | Default | Type | Length | Description |
|---|---|---|---|---|---|
| templateRef | Yes | - | String | 1-255 | The unique alphanumeric template reference. Copy templateRef from the template details page in ShieldConex Manager.See ShieldConex templates for configuration instructions. |
| omit | No | false | Boolean | - | Set to true to exclude tokens from the response and retrieve them with a later tokenization read. Set store to true when you use this flow. |
| store | No | false | Boolean | - | Set to true to store the BFID for a later tokenization read. With omit: false, you receive tokens immediately and retain the option to read them later.With store: false, a tokenization read using the returned bfid fails because ShieldConex cannot find it.This setting does not affect detokenization when you already have the tokenized values. |
| reference | No | - | String | 1-255 | Your reference for tracking requests and responses. This value serves only a tracking purpose. |
| values | Yes | - | Array | - | An array of objects containing name and value. Match each name to a field configured in the template identified by templateRef. |
{
"action": "tokenization-tokenize",
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e47",
"payload": {
"templateRef": "152a4e3f7f31f0a746388adbae1b47f5",
"omit": false,
"store": true,
"reference": "myref",
"values": [{
"name": "scx_token_card_number",
"value": "[redacted card number]"
}]
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e47",
"action": "tokenization-tokenize",
"messageId": "1201911201201321031626749",
"success": true,
"payload": {
"bfid": "[redacted BFID]",
"values": [{
"name": "scx_token_card_number",
"value": "[redacted token]"
}]
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e47",
"action": "tokenization-tokenize",
"messageId": "1201911201201321031626749",
"success": false,
"payload": {
"errorCode": 1202,
"message": "Template not found"
}
}Tokenization Read
Send tokenization-read with a BFID to retrieve tokenized values from a ShieldConex iFrame transaction or a WebSocket tokenization request that used store: true. ShieldConex returns tokenized values, not the original data. Perform this read once per BFID.
Store the BFID before readingSet
storetotruein your WebSocket tokenization request to make its BFID available for a later read. Otherwise, ShieldConex returns an error indicating that it cannot find the BFID.For REST requests, see tokenization request configuration and the
omitflag. Token expiration in your template also limits how long you can use a token for detokenization; it does not remove the one-read-per-BFID restriction.
The payload object contains the following fields:
| Property | Required | Type | Length | Description |
|---|---|---|---|---|
| bfid | Yes | String | 30–150 | The identifier ShieldConex returned for the original tokenization request. Use it to identify the data to read. |
| reference | No | String | 1–255 | Your reference for tracking requests and responses. This value serves only a tracking purpose. |
{
"action": "tokenization-read",
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e46",
"payload": {
"reference": "my_ref",
"bfid": "[redacted BFID]"
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e46",
"action": "tokenization-read",
"messageId": "1201911201201321031626749",
"success": true,
"payload": {
"bfid": "[redacted BFID]",
"values": [{
"name": "scx_token_card_number",
"value": "[redacted token]"
}]
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e46",
"action": "tokenization-read",
"messageId": "1201911201201321031626749",
"success": false,
"payload": {
"errorCode": 1203,
"message": "Not found"
}
}If you receive error 1203, check that you used the BFID from the original transaction and, for WebSocket tokenization, set store: true. Also check whether your workflow has already read that BFID.
Detokenize
Send tokenization-detokenize to recover the original data from tokenized values. Include the BFID from the original tokenization request and the corresponding tokens.
The payload object contains the following fields:
| Property | Required | Type | Length | Description |
|---|---|---|---|---|
| bfid | Yes | String | 30–150 | The identifier ShieldConex returned for the original tokenization request. |
| reference | No | String | 1–255 | Your reference for tracking requests and responses. This value serves only a tracking purpose. |
| values | Yes | Array | — | Objects containing name and the corresponding tokenized value. Match field names to the template used in the original tokenization request. |
{
"action": "tokenization-detokenize",
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e45",
"payload": {
"reference": "my_ref",
"bfid": "[redacted BFID]",
"values": [
{
"name": "scx_token_card_number",
"value": "[redacted token]"
}
]
}
}{
"traceId": "b12be111-51a3-4b2e-b0bd-f79cb30f6e45",
"action": "tokenization-detokenize",
"messageId": "1201911201201321031626749",
"success": true,
"payload": {
"values": [{
"name": "scx_token_card_number",
"value": "[redacted card number]"
}]
}
}Check success before using returned values. If it is false, inspect payload.errorCode and payload.message through your secure error-handling workflow. Keep original data, tokens, BFIDs, and credentials out of application logs.
Updated 17 days ago
