Access Gateway Outbound Host API
Card Payments

Card Payments

Card payments are tapped (NFC), inserted or swiped on a SoftPOS device. MineSec decrypts the card data, builds an EMV message and sends it to your adapter. Your adapter authorizes it with your host and returns respCode.

Endpoints

EndpointPurposeWhen MineSec calls it
POST {baseUrl}/transactionsSale, refund, pre-auth, completion, void, reversalAlways
POST {baseUrl}/sign-onsOpen a session for a terminal before transactionsOnly if sign-on is enabled for your account
POST {baseUrl}/sign-offsClose the sessionOnly on an explicit sign-off
POST {baseUrl}/settlementsBatch totalsOnly if host settlement is enabled for your account
POST {baseUrl}/batch-uploadsRe-send each approved transaction when totals do not matchAfter a 95 answer to /settlements

Sign-on and host settlement are set per account during onboarding. When they are off, MineSec never calls /sign-ons or /settlements and closes batches on its side. We still recommend answering respCode: "00" on every card endpoint, so that enabling them later needs no change on your side.

Transaction lifecycle

Timeout and reversal

If a request that creates a transaction (a sale, refund, pre-auth or completion) gets no response within the read / write timeout, MineSec declines it and reverses it at once. The reversal is the same transaction sent again with isReversal: true, the same enbrTranId, actionType and x-minesec-request-id. Your adapter must undo the original if it was approved.

If the original never reached your host, there is nothing to undo: answer 00. A reversal that is not answered 00 stays pending, and MineSec sends it again before the next transaction or settlement on the same batch. Until it is cleared, those requests fail.

TimeoutValueReversal triggered?
Connection3 sNo
Read / write30 sYes, for a sale, refund, pre-auth or completion
  • Voids are not reversed automatically on timeout.
  • A response that cannot be parsed is a decline, with no reversal. The HTTP status code is not used; only respCode is.

Settlement and batch upload

When host settlement is enabled, /settlements carries the batch totals grouped by transaction type, status and payment method. If your totals do not match, answer respCode: "95". MineSec then sends every approved transaction in the batch to /batch-uploads, and sends the settlement again with isSecond: true.

Transaction types

tranType says what the transaction is. actionType says what is being done to it.

OperationtranTypeactionTypeReference to the original
SaleSALENEW
Sale with installmentsSALENEWCarries installment; see Installment
Refund, card read againREFUNDNEWlinkedEnbrTranId when the POS links it to a sale
Refund without cardREFUNDLINK_REFUNDlinkedEnbrTranId, orgRrn, orgApprovalCode, orgTrace, orgSaleDate
Pre-authorizationAUTHNEW
Completion, card read againAUTH_COMPNEWlinkedEnbrTranId when the POS links it to a pre-auth
Completion without cardAUTH_COMPAUTH_COMPlinkedEnbrTranId, orgRrn, orgApprovalCode, orgTrace, orgAuthDate
Voidoriginal typeVOIDSame enbrTranId as the original; orgTrace, orgRrn, orgApprovalCode, and orgAuthDate (void of a pre-auth) or orgSaleDate (void of a sale or completion)
Reversalas originalas originalSame enbrTranId, isReversal: true

A refund and a completion are transactions of their own, with their own enbrTranId. Tip adjustment and incremental authorization are not supported on the Host API.

Example

POST /api/v1/transactions
{
  "enbrTranId": "tran_01JKF44JBWRNH1AG0GMMKA1M1B",
  "trace": "044883",
  "posReference": "4cea38d1-2d78-4833-8cef-4980b9406d94",
  "profileId": "prof_01JDK7CS51N7DM47JK9M4R9XPP",
  "acptId": "acpt_01JDK7CS6QKRN5K9BP053H0WBP",
  "primaryMid": "111",
  "primaryTid": "222",
  "tranType": "SALE",
  "actionType": "NEW",
  "isReversal": false,
  "amountValue": "1.00",
  "currency": "HKD",
  "paymentMethod": "VISA",
  "entryMode": "NFC",
  "cvmPerformed": "PIN",
  "merchantDevice": "SOFTPOS",
  "cardData": {
    "5F2A": "0344",
    "82": "0020",
    "84": "a0000000031010",
    "95": "0000000000",
    "9A": "250207",
    "9C": "00",
    "9F02": "000000000100",
    "9F10": "1f220100a000000000564953414c335445535443415345000000000000000000",
    "9F1A": "0344",
    "9F26": "a7265f79058a97dc",
    "9F27": "80",
    "9F36": "0002",
    "9F37": "865f8a02"
  },
  "pinBlock": { "pinKsn": "FFFF0000000000100001", "data": "8617b4d7bfc185ce" },
  "track2Data": {
    "track2Ksn": "FFFF0000000000100002",
    "data": "a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718",
    "track2Length": 38
  },
  "merchantName": "ACME",
  "merchantAddress": "No. 7, Park Avenue, Sunset Beach",
  "mcc": "5999",
  "batchNo": "029290",
  "batchId": "batch_01JKF2QRZJFZ5BHF0SC0X9ZR5M",
  "timestamp": "2025-02-07T02:34:33.732Z"
}
Response (200)
{
  "respCode": "00",
  "respMessage": "Approved",
  "approvalCode": "A1B2C3",
  "rrn": "503802123456",
  "hostReferenceId": "host-7f3a9c"
}
  • cardData is a map of EMV tag (hex) to value (hex), ready to map into ISO 8583 field 55.
  • Return rrn and approvalCode from your host. MineSec sends them back on voids, refunds and reversals.
  • If sign-on is enabled for your account, add "extra": {"requireSignOn": "true"} to a transaction response to ask MineSec to sign on again before the next request.

Full field lists: Data Model › Card.

Other card messages

The IDs below continue the transaction example above.

Sign-on

Sent only if sign-on is enabled for your account. /sign-offs uses the same request body; its response has no hostReferenceId.

POST /api/v1/sign-ons
{
  "trace": "044880",
  "primaryMid": "111",
  "primaryTid": "222",
  "profileId": "prof_01JDK7CS51N7DM47JK9M4R9XPP",
  "acptId": "acpt_01JDK7CS6QKRN5K9BP053H0WBP",
  "timestamp": "2025-02-07T10:30:00.105+08:00"
}
Response (200)
{
  "respCode": "00",
  "respMessage": "OK",
  "hostReferenceId": "host-ref-1234567890"
}

Settlement

Sent only if host settlement is enabled for your account. summary has one entry per transaction type, status and payment method in the batch.

POST /api/v1/settlements
{
  "trace": "044951",
  "batchId": "batch_01JKF2QRZJFZ5BHF0SC0X9ZR5M",
  "batchNo": "029290",
  "primaryMid": "111",
  "primaryTid": "222",
  "profileId": "prof_01JDK7CS51N7DM47JK9M4R9XPP",
  "acptId": "acpt_01JDK7CS6QKRN5K9BP053H0WBP",
  "isSecond": false,
  "summary": [
    {
      "tranType": "SALE",
      "tranStatus": "APPROVED",
      "paymentMethod": "VISA",
      "count": 2,
      "total": { "value": "3.00", "currency": "HKD" }
    },
    {
      "tranType": "REFUND",
      "tranStatus": "APPROVED",
      "paymentMethod": "VISA",
      "count": 1,
      "total": { "value": "1.00", "currency": "HKD" }
    }
  ],
  "timestamp": "2025-02-07T15:00:00.418Z"
}
Response (200): totals match
{
  "respCode": "00",
  "respMessage": "Success",
  "hostReferenceId": "host-ref-1234567891"
}
Response (200): totals do not match
{
  "respCode": "95",
  "respMessage": "Batch mismatch"
}

After a 95, MineSec sends each approved transaction to /batch-uploads, then the same settlement again with "isSecond": true and a new trace.

Batch upload

The body is a card transaction request for the original transaction, with these differences:

  • trace is new; orgTrace, orgRrn and orgApprovalCode carry the original's trace, rrn and approvalCode.
  • isReversal is always false; actionType is the original's.
  • The x-minesec-request-id header is the original transaction's.
POST /api/v1/batch-uploads
{
  "enbrTranId": "tran_01JKF44JBWRNH1AG0GMMKA1M1B",
  "trace": "044952",
  "posReference": "4cea38d1-2d78-4833-8cef-4980b9406d94",
  "profileId": "prof_01JDK7CS51N7DM47JK9M4R9XPP",
  "acptId": "acpt_01JDK7CS6QKRN5K9BP053H0WBP",
  "primaryMid": "111",
  "primaryTid": "222",
  "tranType": "SALE",
  "actionType": "NEW",
  "isReversal": false,
  "amountValue": "1.00",
  "currency": "HKD",
  "paymentMethod": "VISA",
  "entryMode": "NFC",
  "cvmPerformed": "NO_CVM",
  "merchantDevice": "SOFTPOS",
  "cardData": {
    "5F2A": "0344",
    "82": "0020",
    "84": "a0000000031010",
    "9F02": "000000000100",
    "9F26": "a7265f79058a97dc",
    "9F36": "0002",
    "9F37": "865f8a02"
  },
  "merchantName": "ACME",
  "merchantAddress": "No. 7, Park Avenue, Sunset Beach",
  "mcc": "5999",
  "orgTrace": "044883",
  "orgRrn": "503802123456",
  "orgApprovalCode": "A1B2C3",
  "batchNo": "029290",
  "batchId": "batch_01JKF2QRZJFZ5BHF0SC0X9ZR5M",
  "timestamp": "2025-02-07T02:34:33.732Z"
}
Response (200)
{
  "respCode": "00",
  "respMessage": "Success"
}

Full field lists: Sign-on, Settlement.

PIN and Track2

MineSec re-encrypts the PIN block and Track2 under keys agreed with you through a key ceremony. The acceptance of your profile names them: pinDestKeyAlias (required for card) and track2DestKeyAlias (optional). See Create the profile.

DataFieldProtection
PIN blockpinBlockTranslated in an HSM under your PIN key. ISO format 0 for a TDES key, format 4 for an AES key. pinKsn is present for a DUKPT key and left out for a static key
Track2track2DataDUKPT-encrypted under your Track2 key, with track2Ksn and track2Length. Sent only if a Track2 key is set up

EMV tags 99 and 57 are never sent in cardData. Without a Track2 key, Track2 is not sent at all.

Recovering Track2

Before encryption, Track2 is zero-padded to the cipher block size (8 bytes for TDES, 16 for AES). To recover it:

  1. Derive the data key from track2Ksn and decrypt data.
  2. Hex-encode the result.
  3. Keep the first track2Length hex characters. The rest is padding.
track2Length     : 38                                   (hex characters, = 19 bytes)
decrypted (hex)  : 4176662220010034123D3112201115233580000000000000
Track2           : 4176662220010034123D311220111523358000

Installment

An installment sale is a tranType: SALE that carries an installment object. MineSec validates the plan for the merchant before sending it; do not recalculate interest or amortization.

{
  "tranType": "SALE",
  "actionType": "NEW",
  "amountValue": "1000.00",
  "currency": "HKD",
  "installment": {
    "installmentCount": 6,
    "interestModel": "NO_INTEREST",
    "installmentType": "REVOLVING",
    "externalPlanCode": "BNK06",
    "revolving": {
      "initialPaymentAmount": { "value": "100.00", "currency": "HKD" },
      "remainingAmount": { "value": "900.00", "currency": "HKD" }
    }
  }
}
  • interestModel is NO_INTEREST or WITH_INTEREST.
  • externalPlanCode and issuerPreapprovalReference are optional.
  • REGULAR: revolving is left out.
  • REVOLVING: amountValue is split into initialPaymentAmount and remainingAmount; installmentCount applies to remainingAmount.
  • The same installment object is carried on the reversal, void and batch upload of the sale.
  • The older tranType: INSTALL does not carry an installment object.

Implementation checklist: verify the signature when signing is enabled; de-duplicate on enbrTranId + actionType + isReversal; always answer HTTP 200; answer 00 to a reversal of a transaction you never received; and return rrn on every approval.