Healthcare Auto-Substantiation

Overview

This scenario is commonly encountered in the US, where specific cards are used for healthcare expenses. For example, in the US, employers give out FSA cards and load money onto the card, which is used exclusively for healthcare payments.

Healthcare-based transactions can either be Card Present (CP) or Card Not Present (CNP). With healthcare expenses, CITs/MITs for recurring payments can be applied on the healthcare-specific cards.

For example, if a person purchases $10 worth of items, and $5 of that amount qualifies as a healthcare expense, only the $5 portion would be approved if the card is designed for healthcare purchases. The merchant would then need to process a separate $5 transaction to cover the remaining amount, either through cash or a standard payment card.

📘

Healthcare Purchases

These purchases can include prescription, vision care, dental care, clinical or medical services, copay or transportation expenses as listed in the healthcare metadata.

Transaction Flow

The following diagram is the same as in the CITs/MITs Use Case with the addition of allowPartial and the issuing bank specifically having to check for the healthcare metadata.

Healthcare Auto-Substantiation Transaction flow with the PayConex™ API

Healthcare Auto-Substantiation Transaction Flow with the PayConex™ API

  1. CIT Processing: A customer initiates a transaction (CIT). This is the merchant server/ECR/POS system making a request via PayConex™ V4 API.

  2. Detokenization/Decryption: The V4 API sends the payload to the Decryptx®(CP, MOTO)/ShieldConex®(CNP) for processing (decryption/detokenization).

  3. Forwarding: Decryptx®/ShieldConex® forwards the decrypted or detokenized elements to PayConex™ services, in this case the PayConex™ Gateway.

  4. Partial Authorization: The PayConex™ Gateway communicates with the Payment Processor where allowPartial tells the Processor to approve a partial amount with the card issuers. This process is fully PCI-compliant.

  5. Metadata Check: The issuing bank checks for the healthcare-related metadata coming through the PayConex™ Gateway and the Processor, asking the bank for the purpose of the specific healthcare expense.

  6. Issuer Distinction and Approval: The card issuers are notified about CIT/MIT and the partial amount as a healthcare expense for authorization.

  7. Auto-Tokenization: In the case of CITs, the Processor responds to the PayConex™ V4 API with an async process for auto-tokenization via ShieldConex® on the way back.

  8. Vaulting: As CITs, the PayConex™ Services vault the token for recurring purposes.

  9. Reissuing Token: The V4 API returns the reissuing token to the merchant (origin).

  10. Recurring Cycle: The merchant is able to run MITs on a regular basis based on a prior agreement with a customer. As the legends suggest, the merchant can either implement their own recurring solution or use one provided by Bluefin.

As documented in the transaction metadata section, once the healthcare transaction is processed, the PayConex™ V4 API does the following:

  • Populates the healthcard and binData fields accordingly.
  • Assigns amounts.approved to determine what amount was approved.
  • Sets the auth.message to "PARTIALLY APPROVED" or "APPROVED" if successful.

Approved Healthcare Purchase

Request

{
  "amounts": {
    "currency": "USD",
    "total": "10.00"
  }
}

Response

This is the transaction metadata of an approved healthcare purchase.

{
  "transactionId": "000000047126",
  "status": "CAPTURED",
  "timestamp": "2025-04-04T12:42:16.000000Z",
  "trace": {
    "customId": "abc123",
    "source": "PCX V4",
    "history": [
      {
        "action": "transaction",
        "requestId": "68950ebc-d196-471b-959a-6438c06f0d57",
        "correlationId": "85cad1f7-ef9c-45f0-a606-731fe5f7d0b4",
        "timestamp": "2025-04-04T07:42:14-05:00"
      }
    ],
    "networkTransactionId": "015094350820714CN  "
  },
  "amounts": {
    "currency": "USD",
    "approved": "10.00",
    "requested": "10.00",
    "balance": "10.00"
  },
  "healthcare": {
    "totalAmount": "10.00",
    "prescription": "10.00",
    "vision": "0.00",
    "dental": "0.00",
    "clinical": "0.00",
    "copay": "0.00",
    "transit": "0.00"
  },
  "auth": {
    "code": "OK1290",
    "processorMessage": "APPROVED",
    "message": "APPROVED",
    "networkName": "VISA"
  },
  "card": {
    "last4": "0043",
    "expiry": "1230",
    "brand": "VISA"
  },
  "binData": {
    "program": "HEALTHCARE",
    "programCard": "FSA"
  },
  "transactionType": "SALE",
  "entryMode": "KEYED",
  "refundObject": {
    "refundBalance": "10.00"
  }
}

Partially-approved Healthcare Purchase

In case we are making a purchase that includes healthcare in addition to the original payment, the amounts.total usually exceeds the healthcare expenses, enabling the Partial Authorization.

🚧

Note

Note that the healthcare object can be additionally included for both CP and CNP transactions. This is needed for subsequent MITs.

If the healthcare data is provided this way and the card is not designed for healthcare purchases, the PayConex™ Gateway drops this data.

In the following request, the allowPartial is not required if it is enabled by default via Allow API Override.

Request

{
  "rules": {
    "allowPartial": true
  },
  "amounts": {
    "currency": "USD",
    "total": "30.00"
  }, 
  "healthcare": {
    "totalAmount": "10.00",
    "prescription": "10.00"
  }
}

healthcare

Here are the healthcare request parameters for a CP/CNP transaction.

ParameterTypeDescription
totalAmountstring (Numeric decimal)The total amount of the transaction or cost.
prescriptionstring (Numeric decimal)The amount associated with prescription expenses.
visionstring (Numeric decimal)The amount related to vision care expenses.
dentalstring (Numeric decimal)The amount related to dental care expenses.
clinicalstring (Numeric decimal)The amount related to clinical or medical services.
copaystring (Numeric decimal)The amount the patient must pay out-of-pocket as a co-pay.
transitstring (Numeric decimal)The amount associated with transit or transportation costs.

🚧

Healthcare and Amounts Total

{
"amounts": {
"currency": "USD",
"total": "5.00"
}, 
"healthcare": {
"totalAmount": "10.00",
"prescription": "10.00"
}
}

If the amounts.total doesn't, at least, sum up to the healthcare total as above, we receive the following error response:

{
"message": "Sum of the healthcare amounts cannot exceed the total amount",
"errorCode": 40001,
"errorType": "invalid_request",
"source": "healthcare",
"traceId": "4d4e0965-744a-4c4b-8ca3-8d90a1973eb2",
"details": [
{
"source": "healthcare",
"value": {
  "totalAmount": "10.00",
  "prescription": "10.00"
},
"message": "Sum of the healthcare amounts cannot exceed the total amount"
}
]
}

Response

If we look at the authorization object of the partially approved healthcare transaction, we can see:

"auth": {
  "code": "OK1690",
  "processorMessage": "Approve for partial amount",
  "message": "PARTIALLY APPROVED",
  "networkName": "VISA"
},
{
  "transactionId": "000000047166",
  "status": "CAPTURED",
  "timestamp": "2025-04-04T12:43:11.000000Z",
  "trace": {
    "customId": "abc123",
    "source": "PCX V4",
    "history": [
      {
        "action": "transaction",
        "requestId": "bdd39019-af02-4720-88ca-a232ffeaec67",
        "correlationId": "ae57d4b0-aefa-4db7-b27b-2e26805c6a0d",
        "timestamp": "2025-04-04T07:43:09-05:00"
      }
    ],
    "networkTransactionId": "015094384848019CN  "
  },
  "amounts": {
    "currency": "USD",
    "approved": "10.00",
    "requested": "30.00",
    "balance": "10.00"
  },
  "healthcare": {
    "totalAmount": "10.00",
    "prescription": "10.00",
    "vision": "0.00",
    "dental": "0.00",
    "clinical": "0.00",
    "copay": "0.00",
    "transit": "0.00"
  },
  "auth": {
    "code": "OK1690",
    "processorMessage": "Approve for partial amount",
    "message": "PARTIALLY APPROVED",
    "networkName": "VISA"
  },
  "card": {
    "last4": "0043",
    "expiry": "1230",
    "brand": "VISA"
  },
  "binData": {
    "program": "HEALTHCARE",
    "programCard": "FSA"
  },
  "transactionType": "SALE",
  "entryMode": "KEYED",
  "refundObject": {
    "refundBalance": "10.00"
  }
}