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:

  1. Join your partnerId and partnerKey with a colon: partnerId:partnerKey.
  2. Base64-encode the resulting string without adding a newline.
  3. Set the header to Authorization: Basic followed 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 NameWebSocket Connection URL
Staging Environmentwss://secure-staging-ws.shieldconex.com
Certification/Testing Environmentwss://secure-cert-ws.shieldconex.com
Production Environmentwss://secure-ws.shieldconex.com

Request Message Structure

Request JSON messages have the following properties:

PropertyRequiredTypeLengthDescription
traceIdYesString0-255Choose 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.
actionYesEnumeration-Choose the action to perform:
heartbeat
partner-validate
template-validate
tokenization-tokenize
tokenization-read
tokenization-detokenize
payloadYes, except for heartbeatJSON-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:

PropertyDescription
traceIdMatches the traceId you sent in the request.
actionIdentifies the action ShieldConex performed.
messageIdIdentifies the transaction. Use this system-generated value to track the message in the portal.
successReports whether ShieldConex processed the message successfully.
payloadContains 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.

  1. Install the WebSocket library: python -m pip install websockets.
  2. Select a template in your certification environment and copy its templateRef from ShieldConex Manager.
  3. Save the code as scx_action.py and run python scx_action.py from 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:

PropertyRequiredTypeLengthDescription
referenceNoString1–255Your 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:

PropertyRequiredTypeLengthDescription
referenceNoString1–255Your reference for tracking requests and responses. This value serves only a tracking purpose.
templateRefYesString1–255The 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:

PropertyRequiredDefaultTypeLengthDescription
templateRefYes-String1-255The unique alphanumeric template reference. Copy templateRef from the template details page in ShieldConex Manager.
See ShieldConex templates for configuration instructions.
omitNofalseBoolean-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.
storeNofalseBoolean-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.
referenceNo-String1-255Your reference for tracking requests and responses. This value serves only a tracking purpose.
valuesYes-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 reading

Set store to true in 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 omit flag. 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:

PropertyRequiredTypeLengthDescription
bfidYesString30–150The identifier ShieldConex returned for the original tokenization request. Use it to identify the data to read.
referenceNoString1–255Your 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:

PropertyRequiredTypeLengthDescription
bfidYesString30–150The identifier ShieldConex returned for the original tokenization request.
referenceNoString1–255Your reference for tracking requests and responses. This value serves only a tracking purpose.
valuesYesArray—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.


Did this page help you?