Card Issuing

Real-time Decisioning

API Documentation

Column allows your platform to make card authorization decisions in real-time. When Column receives authorization requests from the card networks, the Bank will send a webhook to your system and await a decision. This functionality can be used in conjunction with Column's authorization policy API to ensure only permitted transactions are approved.

Decisioning Flow

When an approval request is received by Column from the card networks, the following approval process is followed:

  1. Column will match the request to a Card & Card Account in the system. If Column cannot resolve the request to a card, it is automatically declined. If your platform is allocated an entire BIN, Column can send an event webhook when an authorization is declined due to an invalid account number on your behalf.
  2. Column will check the status of the Card & Card Account, and if the status is not active, Column will decline the transaction with the appropriate decline code and send your system an event webhook.
  3. Column checks the account type, address verification (AVS) results, and currency of the request, and declines the transaction if any of these checks fail.
  4. Column evaluates any authorization policies configured by your system using the Authorization Policy API. If a policy is triggered, Column will decline the transaction on your behalf and send an event webhook.
  5. Column performs fraud checks on the request.
  6. Column will perform a balance check to ensure sufficient funds are available, if not, the transaction will be declined, and an event webhook will be sent to your system. Note: alternate funding models such as Just-in-time or transfer upon approval can be configured, please reach out to design a flow of funds if these models are needed.
  7. Column will send a Real-time decision webhook to your system and will wait a total of 3 seconds for a response. If no response or an invalid response is received, Column will decline the transaction.

Note: all decisioning information is included in the decisioning_details struct in the Card Transaction Event.

Webhook Setup

To enroll an endpoint to receive real-time decisioning events the existing webhook endpoints API can be used with the specific event type of decision.issuing.card_transaction. Real-time decisioning events will have the same Column-Signature header that can be used to validate the request originated from Column.

It is recommended to use a different endpoint for real-time decisioning that is optimized for latency since there is a 3-second deadline for responses.

The endpoint must return the real-time decision response shape, such as a decision value of approve, decline, or partially_approve. Responses that do not include a recognized decision value are treated as invalid and Column will decline the authorization. If you are using the local example webhook server, register the authorization route /webhooks/cards/authorizations for this event type. This route is distinct from the token provisioning routes, such as /webhooks/cards/tokens.

Note: if your system fails to respond to a real-time decisioning request, Column will not retry the request and decline the authorization. Column also has a deadline to respond to the card networks, and it does not provide sufficient time for retries. Column will send a webhook to notify you of the decline, and the decision_reason in decisioning_details indicates what went wrong:

Decision Reason
Description
realtime_authorization_endpoint_missing
No webhook endpoint is registered for decision.issuing.card_transaction.
realtime_authorization_request_timeout
Your endpoint did not respond within the deadline.
realtime_authorization_connection_error
Column could not connect to your endpoint.
realtime_authorization_invalid_response
Your endpoint returned a response Column could not use, such as an unrecognized decision value or an invalid partial approval.
error
Your endpoint returned a non-success HTTP status. The decision_source is platform_owner.

Real-time Decision Object

The real-time decision object contains the fields card_transaction, proposed_event, and, when Column has computed the card account's balance, available_balance. If the decision relates to a new transaction, the transaction and proposed event will both be created after the response is returned. If the decision relates to an existing event (for example, the request is for an incremental auth), the card_transaction will contain the existing card transaction, and the proposed event will be appended to the existing transaction.

3DS Authentication Decisioning

You can also make real-time decisions during 3DS authentication, before a challenge is shown. Subscribe a webhook endpoint to decision.issuing.card_authentication. Column sends the 3DS authentication decision request to that endpoint with the authentication attempt and available network context. Return a 3DS authentication decision response with one of these decisions:

  • frictionless_approve recommends that the network's risk system authenticate without a cardholder challenge.
  • challenge proceeds to a cardholder challenge.
  • decline_authentication rejects the authentication. You may return decline_reason as suspected_fraud or transaction_not_permitted; Column defaults to suspected_fraud when the reason is omitted.

Column waits up to 1 second for a valid response. A timeout, connection error, non-success response, or invalid response fails safe to challenge. This differs from card authorization decisioning, which waits up to 3 seconds and declines when your endpoint does not return a valid decision. Column does not retry either decision request within the network deadline.

frictionless_approve is a recommendation to the network's risk system and might not produce a frictionless result in every flow. A challenge decision fails authentication if the cardholder has no supported challenge method, such as an email address on the person entity. Data-only authentications with merchant challenge indicator 06 do not invoke your decision endpoint.

Sandbox Testing

Call POST /simulate/issuing/cards/:card_id/threeds/challenge in sandbox. Set realtime_decision to exercise a specific decision without calling your endpoint, and optionally set decline_reason for a declined authentication. Omit realtime_decision to invoke a sandbox endpoint subscribed to decision.issuing.card_authentication. If no subscribed endpoint exists, the simulator preserves its default behavior and creates an OTP challenge.

Decline Reasons

If you decide to decline a transaction, you can optionally specify a decline_reason to provide more information to the merchant who originated the request. Generally, it is best practice and more user-friendly for cardholders to include a reason for a decline. Additionally, some card networks assess additional fees if general decline codes are used.

If a reason isn't specified in the real-time decision response, Column will return a generic "do not honor" response code.

Partial Approvals

Some card networks and merchants support partial approvals. This allows your platform to approve a subset of the requested amount. An example of this is if a debit card had a remaining balance of $10 but is used to purchase a $50 item. If you opt to partially approve $10, the merchant will apply $10 and then request an alternate form of payment for the remaining $40.

In the real-time decisioning request, the field can_support_partial_approvals field indicates whether the merchant supports partial approvals. You can then return the decision choice of partially_approve with an amount set in partially_approve_amount. If your system returns partially_approve when it is unsupported, without an amount, with a zero amount, or with an amount greater than the requested amount, Column will decline the transaction with the realtime_authorization_invalid_response reason. A partially_approve response with an amount equal to the requested amount is recorded as a partial approval of the full amount.

Partial approvals are not supported for incremental authorizations or reauthorizations. Column declines a partially_approve response to those requests with the realtime_authorization_invalid_response reason.

For automated fuel dispenser transactions that support partial approvals, if the card account's available balance is lower than the requested amount, Column limits the proposed event to the available balance before sending the real-time decision request instead of declining for insufficient funds. Respond with partially_approve (or decline) in this case; an approve response is declined with the realtime_authorization_invalid_response reason.