Skip to main content
Guides

Real-time decisions

We recommend first reading our Webhooks guide for background.

Overview

Real-time decisions let your application respond to a card network request before we return a response to the network. For example, you can evaluate an authorization against a spending limit maintained in your own ledger. We create a Real-Time Decision object and send you a real-time webhook. Your application retrieves the request and submits its decision within the network’s deadline.

Real-time webhooks

Real-time webhooks are sent immediately and delivered to a single Event Subscription. Set selected_event_categories to the single real-time category you want to handle. Only one active Event Subscription can handle a given real-time event category.

We send an Event that references the Real-Time Decision. Your webhook handler must retrieve that decision, submit a response with POST /real_time_decisions/{id}/action to the action endpoint, and wait for that API request to complete before acknowledging the webhook with HTTP 200. Responding to the webhook alone does not action the decision. Because of the short deadline, we do not retry real-time webhooks that fail to return HTTP 200.

Real-time decisions

The time available to respond depends on the category:

CategoryTime to decide
card_authorization_requested4 seconds
card_balance_inquiry_requested4 seconds
card_authentication_requested2 seconds
card_authentication_challenge_requested2 seconds
digital_wallet_token_requested2 seconds
digital_wallet_authentication_requested2 seconds

Every Real-Time Decision exposes a timeout_at timestamp, which is the authoritative deadline for that decision. Retrieval, your decision logic, and the action request must all complete before that deadline.

For authentication and challenge delivery, see 3D Secure. For token provisioning and verification code delivery, see Digital wallets.

Example: responding to card authorizations in real time

An authorization is a request from the merchant’s acquirer, the financial institution that submits its card transactions, to the issuer, the financial institution that issued the card. The issuer’s response determines whether the requested amount is authorized. Your handler can approve the full amount, approve a smaller amount when the merchant supports partial approval, or decline with a reason. An approval can also include an address verification result for the acquirer to evaluate.

Create an Event Subscription with real_time_decision.card_authorization_requested in its selected categories. The webhook Event identifies the decision to retrieve. This excerpt shows the relevant fields; identifiers will differ for each request:

{
  "associated_object_id": "real_time_decision_9xgp7q7jjsnlfz8wz6z8",
  "associated_object_type": "real_time_decision",
  "category": "real_time_decision.card_authorization_requested",
  "type": "event"
}

Use associated_object_id to retrieve the Real-Time Decision with GET /real_time_decisions/{id}. Its authorization details include the amount, merchant, transaction type, verification results, and network risk score. See the API reference for the request shape.

Evaluate the transaction’s purpose as well as its amount and merchant. A purchase, a refund authorization, and a cash disbursement need different rules. Check request_details.category before treating the request as a new purchase: an incremental authorization increases an earlier authorization. Its request details identify the original authorization and Card Payment, so you can account for the amount already authorized.

Verification results and the network risk score provide additional inputs to your decision. A result of not_checked does not establish that the supplied credentials match. Visa’s risk score ranges from 0 to 99, with higher scores indicating greater fraud risk. Combine these signals with state your application maintains, such as recent spending across a cardholder’s cards. See Card issuing fraud controls for how these decisions interact with Increase’s controls.

Approving the full amount or a partial amount

Approve the full amount when the request meets your authorization rules. Send card_authorization with decision: approve to the action endpoint. Omitting a partial amount approves the requested amount.

A partial approval authorizes less than the merchant requested. Use it when you can authorize some of the amount, such as the remaining balance in a cardholder’s spending allocation, and the merchant permits it. The merchant can then collect the remainder through another payment method. Check that partial_approval_capability is supported before returning a partial approval.

For a $100 authorization request, this action body authorizes $60:

{
  "card_authorization": {
    "decision": "approve",
    "approval": {
      "partial_amount": 6000
    }
  }
}

The partial amount must be positive and less than the requested settlement amount, expressed in the minor unit of the settlement currency. If the merchant does not support partial approval, your response must approve the full amount or decline. See the approval shape in the API reference.

Returning an address verification result

You can return an Address Verification System (AVS) result with an approval. The result is advisory to the acquirer, which may reverse an approved authorization if the address does not match. See Address Verification System codes and overrides for how to evaluate addresses and return your own result.

Declining with a reason

Decline when the request fails your authorization rules. Include a reason that describes the failure: insufficient funds when the cardholder’s available funds cannot cover the request, or suspected fraud when your risk rules reject it. We translate the reason into a network response code. This lets the merchant and cardholder receive a response that distinguishes a funding problem from a suspected fraudulent transaction; the merchant controls how that response is displayed.

For example, if your ledger cannot fund the request and you are not returning a partial approval:

{
  "card_authorization": {
    "decision": "decline",
    "decline": {
      "reason": "insufficient_funds"
    }
  }
}

Use card_authorization.decline.reason for this response. The API reference lists the supported reasons.

Timeouts

By default, we decline the authorization if we do not receive your action before the deadline. To configure approvals under specific conditions when your handler times out, contact support@increase.com.

Retrieve the Real-Time Decision afterwards and check for status: timed_out. With the default behavior, the resulting Declined Transaction records webhook_timed_out at source.card_decline.reason, distinguishing a missing response from a decline your handler submitted.

Testing in sandbox

Create an active card with enough available account balance for the authorizations you will approve. Create an Event Subscription in sandbox selecting real_time_decision.card_authorization_requested. Configure your handler to retrieve and action decisions at https://sandbox.increase.com using your sandbox API key. Replace the example card identifier below with your card’s identifier.

Simulate a card authorization to request a $100 purchase authorization:

curl -X "POST" \
  --url "https://sandbox.increase.com/simulations/card_authorizations" \
  -H "Authorization: Bearer ${INCREASE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "card_id": "card_oubs0hwk5rn6knuecxg2",
    "amount": 10000,
    "merchant_descriptor": "OFFICE SUPPLIES",
    "merchant_category_code": "5943",
    "merchant_country": "US",
    "network_risk_score": 10
  }'

Run a new simulation for each response you want to test. Have your handler post one of the action bodies above to /real_time_decisions/{id}/action, using the identifier from that simulation’s webhook. Simulated authorizations support partial approval. They create initial authorizations and omit address and card verification data, so verification results are not_checked.

To test a timeout, let the deadline pass without submitting an action, then retrieve the Real-Time Decision and check its status.