Card Transactions

Card Transactions

A card transaction is defined as a transaction that occurs on a customer issued card. All Synctera payment types utilize the common /transactions resource - see API reference for details.

Transaction Flows

The flow of a transaction is split into two major components:

  • Funding request
  • Clearing

Funding Request

Funding requests are initiated at the time of card usage. When a cardholder initiates a transaction, the merchant sends a request to the network. The network then sends a funding request to Synctera, expecting an approved or denied response. A Pending Transaction is created when the funding request is received, which publishes a webhook) on the transaction.pending.created topic with initial status PENDING.

Synctera then makes a determination on whether to approve or decline the funding request. See declined transactions for more details.

While evaluating the funding request, the Pending Transaction may be updated with supplemental data gathered during the process. A transaction.pending.upated webhook is published when the transaction is updated. For example, enhanced transaction information may be added.

Funding Request Flow

%%{init: {"fontFamily": "sans-serif"}}%%
sequenceDiagram
Customer->>Merchant: Initiate transaction
Merchant->>Network: Request
Network->>Synctera: Funding request
Synctera->>FinTech: Pending transaction created webhook
Synctera->>Synctera: Evaluate funding request
Synctera->>FinTech: Pending transaction updated webhook
Synctera-->>Network: Response
Network-->>Merchant: Response

In addition, the FinTech can elect to participate in the funding request authorization flow - see FinTech in the auth flow - which adds an additional decision point to the evaluation.

Clearing

The transaction is not fully complete until it has cleared. The clearing process causes a transaction to change from pending to posted. This is when money actually moves. Note that pending and posted transactions are distinct resources - see API reference for more details.

After the funding request is approved - sometimes hours - the merchant initiates a request to the network for retrieving the funds for all of their pending transactions. Synctera receives the clearing notification, updates the Pending Transaction and creates a Posted Transaction.

Two webhooks are published when clearing is complete. First, transaction.pending.updated when Pending Transaction status is changed to CLEARED. Second, transaction.posted.created when the Posted Transaction is created.

Clearing Flow

%%{init: {"fontFamily": "sans-serif"}}%%
sequenceDiagram
Merchant->>Network: Request
Network->>Synctera: Notification
Synctera->>FinTech: Pending transaction updated webhook
Synctera->>FinTech: Posted transaction created webhook

Declined Transactions

Transactions may be declined for various reasons, including:

When a transaction is declined, the status is updated to DECLINED. In most cases, a transaction.pending.updated will be issued to signal change of status. However, in the case of network declination, there will only be a transaction.pending.created webhook with initial status of DECLINED.

The data.reason field of the Pending Transaction body contains the reason for why the transaction was declined. Below is a list of reasons and their sources:

Customer/account standing:

  • NO_CHECKING_ACCOUNT
  • NO_SAVINGS_ACCOUNT
  • NO_CREDIT_ACCOUNT
  • CLOSED_ACCOUNT

Fraud:

  • SUSPECTED_FRAUD

Ledger:

  • INSUFFICIENT_FUNDS
  • DISABLED_PAYMENT_TYPE
  • BALANCE_VIOLATION
  • DUPLICATE_TRANSACTION
  • SPEND_CONTROL_VIOLATED (see Spend Controls)

Network stand-in:

  • NETWORK_DECLINED

πŸ“˜

For network declined transactions, there will be additional details under data.user_data.network_decline_details of the Pending Transaction body.

Gateway:

  • GATEWAY_DECLINED
  • GATEWAY_ERROR

General purpose:

  • TRANSACTION_NOT_PERMITTED

πŸ“˜

The list of possible decline reasons is subject to grow, so code should be written defensively around processing declined transactions.

Network Stand-In Scenario

Stand-in scenario happens when a funding request from the network is not responded to in time, so the network must stand in to be the decision maker. It is intended to be a fallback mechanism and not to be consistently relied upon, as there is less control over the decision which may result in undesired money movement.

In rare cases, Synctera may never recieve a funding request and only be informed that a transaction has taken place after the fact. In this case, there will only be a Posted Transaction, no Pending Transaction.

Card Transaction Simulations

Synctera provides a variety of endpoints that simulate card transactions. These endpoints mimic how real transaction will look in a production environment. This gives FinTechs the tools to develop and test their application against the different types of card transactions without any real money movement or financial impact.

All card transaction simulation endpoints are found under the /cards/transaction_simulations path - see API reference for details. These endpoints can only be used in the Synctera Sandbox environment.

This guide will explain how to simulate a selection of typical transaction scenarios.

Merchant Information Fields

Many of these endpoints require a card_acceptor object, which contains merchant information:

{
  "address": "address",
  "city": "city",
  "country": "country",
  "mcc": "mcc",
  "name": "name",
  "state": "state",
  "zip": "zip"
}

The mcc (MCC - Merchant Category Code) field is a universal code assigned to merchants for the purpose of classifying the type of goods and services they provide.

In addition, the top level mid (MID - Merchant Identification Number) field is sometimes required. This is a unique identifier assigned to all merchants that process card transactions.

For simulations, the content used for card_acceptor and mid is not neccesarily important. However, merchant information is often crucial for FinTech in the Auth Flow.

1. Authorization & Clearing

This describes the typical case where a cardholder purchases something from a physical or online merchant. The transaction amount is authorized, then later cleared. To simulate this scenario, an authorization, then clearing is performed. Note that an authorization equates to a funding request.

To simulate, first call Simulate authorization, providing the appropriate card_id, along with the authorization amount. This will generate an authorization (funding request), which applies a hold for the given amount of money and creates a Pending Transaction. On a successful call, a transaction token is generated. The token is needed for clearing.

Next, call Simulate clearing or refund with the same amount as was used in the authorization and original_transaction_id set to the authorization transaction token.

2. Authorization Adjustment

In some circumstances, a merchant may want to authorize for a different amount than what is ultimately cleared. For example, at a gas pump, it is common for a customer to pre-authorize up to a certain amount, but only be charged for the amount of gas that was actually pumped. In this case, an initial authorization is created for the pre-authorized amount. Once the final sale price is determined, an authorization advice is performed to adjust the hold. Like the previous scenario, a final clearing is done to capture the funds.

To simulate, first call Simulate authorization like in the previous example and retain the transaction token.

Next, issue an authorization advice with Simulate authorization advice, providing the new amount and original_transaction_id (token).

Finally, issue the clearing with Simulate clearing or refund, using the final amount from the authorization advice and original_transaction_id set to the transaction token from the original authorization response.

3. Reversals & Refunds

Reversals and refunds both refer to the undoing of a previous action, the only difference being the action that is being undone. Reversals release an existing authorization hold and refunds undo a cleared transaction and move funds back to a cardholder's card.

To simulate a reversal, an existing authorization hold must already exist. To issue the reversal, call Simulate reversal, providing the full authorization amount and original_transaction_id set authorization transaction token for original_transaction_id.

Likewise, to simulate a refund, a cleared transaction must already exist. To issue the refund, call Simulate clearing or refund, providing the final amount from the clearing and the original authorization transaction token for original_transaction_id.

4. Single Message

All above listed scenarios involve dual message transactions. Meaning, the transaction occurs in two parts: authorization, then clearing. However, there are also single message transactions, where authorization and clearing occur in a single action. Common examples include PIN-debit transactions and ATM transactions.

Below are descriptions of the common single message simulation endpoint use cases:

  • Simulate financial: This endpoint is used to simulate a PIN-debit transaction - when a cardholder provides their PIN code at the time of purchase. The amount and card_id must be provided.
  • Simulate ATM withdrawal: This endpoint simulates a cash withdrawal from an ATM (Automated Teller Machine). Similarly, amount and card_id must be provided.

Enhanced Transactions

By default, transaction metadata (merchant name, location, category, etc.) is provided by the network - found in the transaction data.user_data object. For the most part, this information is limited and often inconsistently formatted.

If desired, a card product can be configured with a supported third party provider to add enhanced metadata to each transaction. Synctera's current supported enhanced transaction provider is MX.

For example, given the following network provided merchant name and MCC (merchant category code):

{
  "mcc": "4816",
  "name": "EIG*HOSTGATOR.COM"
}

Enhanced transaction can provide a cleanly formatted name and consistent category:

{
  "category": "Hosting",
  "enhanced_description": "HostGator"
}

Enhanced transaction information is found in the transaction data.user_data.enhanced_transaction object. enhanced_raw contains the complete set of data received from the enhanced transaction provider.

{
  "category": "Hosting",
  "enhanced_description": "HostGator",
  "enhanced_raw": [
    {
      "amount": 12.75,
      "categorized_by": 13,
      "category": "Hosting",
      "category_guid": "CAT-b74fdd98-4391-8015-eafa-e9ca0fad3bee",
      "described_by": 6,
      "description": "HostGator",
      "extended_transaction_type": null,
      "id": "2ffa6d90-e4d0-47e3-a290-17240e7a3ae4",
      "is_bill_pay": false,
      "is_direct_deposit": false,
      "is_expense": null,
      "is_fee": null,
      "is_income": false,
      "is_international": null,
      "is_overdraft_fee": false,
      "is_payroll_advance": false,
      "is_subscription": false,
      "memo": "ad0f57f1-f823-4ba7-8563-a1c4aa458371",
      "merchant_category_code": 4816,
      "merchant_guid": "MCH-dae1c6b5-292b-4d3e-ba15-998ab24a79c2",
      "merchant_location_guid": null,
      "original_description": "EIG*HOSTGATOR.COM",
      "type": "DEBIT"
    }
  ]
}

FinTech in the Auth Flow

Authorization Gateway

An authorization Gateway enables a FinTech to optionally take part in the funding request decision of a card transaction’s authorization cycle. The FinTech receives an authorization request via the configured Gateway to either approve or decline the card transaction based on the FinTech's own business logic.

If the fintech opts not to participate in the auth flow Synctera will use default authorization logic to authorize the transactions. The fintech does not have to participate unless there is additional approval logic they would like to incorporate into the decision process that is not supported by Synctera or proprietary in nature.

The authorization request must be responded to within a firm timeout window of 1.5 seconds. Synctera will default to declining the funding request if a response is not received within the timeout window.

The information in the authorization request includes, but is not limited to:

  • Customer/Account/Card ID's
  • Available balance
  • Merchant information
{
  "customer_id": "2b9cc6f2-d0bd-4d9d-aa20-5e53355f9469",
  "account_id": "0221e0a7-7774-48a4-8521-e678ec09a53a",
  "transaction_id": "9b59fc80-9bf5-4749-8dd2-511f183becf2",
  "card_id": "6128498a-85a9-4bd8-a3ea-bfe3717b64f6",
  "card_format": "PHYSICAL",
  "last_four": "1234",
  "type": "card_transaction",
  "user_transaction_time": "2022-03-25T10:41:01-04:00",
  "settlement_date": "0001-01-01T00:00:00Z",
  "amount": {
    "amount": 100,
    "currency": "USD",
    "currency_conversion": {
      "original_amount": 100,
      "conversion_rate": 1,
      "original_currency_code": "840",
      "original_currency_code_alpha": "USD"
    }
  },
  "balance": {
    "available_balance": 4210000
  },
  "merchant": {
    "mid": "4445001899609",
    "mcc": "5411",
    "name": "WHOLEFDS EGW 101",
    "city": "EDGEWATER",
    "state": "NJ",
    "postal_code": "07020",
    "country_code": "USA",
    "sub_merchant_id": "",
    "payment_facilitator_id": ""
  },
  "user": {},
  "network_fraud": {
    "transaction_risk_score": 18
  },
  "network": "MASTERCARD",
  "subnetwork": "",
  "dc_sign": "debit",
  "pos": {
    "pan_entry_mode": "MAG_STRIPE",
    "pin_present": false,
    "terminal_id": "10000000",
    "cvv_presence": "CVV1"
  },
  "processor": "MARQETA",
  "processor_data": {}
}

Addionally, if enhanced transactions are enabled for the FinTech, this information will also be included.

To signal an authorization request decision, the FinTech must reply with the appropriate HTTP code:

  • HTTP code 200: approve the funding request
  • HTTP code 402: decline the funding request

Note that while HTTP code 402 is conventional, any code other than 200 will also be interpreted as a decline.

FinTech Included in Funding Request Authorization Flow

%%{init: {"fontFamily": "sans-serif"}}%%
sequenceDiagram
Customer->>Merchant: Initiate transaction
Merchant->>Network: Request
Network->>Synctera: Funding request
Synctera->>FinTech: Pending transaction created webhook
Synctera->>Synctera: Evaluate funding request
Synctera->>FinTech: Authorization request
FinTech->>FinTech: Evaluate authorization request
FinTech-->>Synctera: Response
Synctera->>FinTech: Pending transaction updated webhook
Synctera-->>Network: Response
Network-->>Merchant: Response

Sandbox Implementation

  1. Create a new Gateway configuration via Synctera API
  2. Generate an authorization card transaction simulation and ensure the Gateway endpoint successfully recieves and responds to the request

πŸ“˜

For local testing, ngrok or beeceptor can be used to produce a publicly accesable URL that terminates to a local development endpoint.

Gateway Endpoint Configuration

To create a Gateway, a valid, publicly accessable URL must be supplied, along with a list of Card Product ID's that will utilize the Gateway. Additionally, customer headers may be supplied that will be included in authorization calls to the Gateway. If not supplied, active status is set to true by default. Gateways may be turned off by setting this field false.

Note that a Card Product may not be configured on more than one active Gateway at a time.

curl \
  -X POST \
  -H "Authorization: Bearer $apikey" \
  -H "Content-Type: application/json" \
  $baseurl/v0/cards/gateways \
  --data-binary '
  {
    "active": true,
    "url": "https://example.com",
    "custom_headers": {
      "key": "value"
    },
    "card_products": [
      "41e81dff-05d4-4421-b7f0-149e3a536979",
      "e8361f07-1e7d-440c-91bd-def3e18a907f"
    ]
  }'