Simulating transactions

Overview#

The purpose of this document is to familiarize you with the transactions you may encounter and the data associated with each kind of transaction. Most of the API calls in this document are only available for the sandbox environment. In the production environment, most transactions are initiated by merchants when they interact with your cardholders.

Now that you have your developer account, API keys, and card design, it's time to simulate the real-world behavior of your card program. This article walks you through a set of example API calls to:

  1. Add funds to a card.
  2. Check the balance of that card.
  3. Authorize and capture funds in a single message (“financial requests”), with examples for declined as well as authorized and cleared.
  4. Authorize and capture in multiple messages (“authorization requests”), with examples for declined as well as authorized and cleared.

If you are not familiar with the transaction authorization process, please read the Transactions article in our developer guides. At this time, we are unable to simulate a reversal.

Prerequisites#

You’ll need your API key (username) and API secret (password) for each API call. So make sure you have those handy. See Creating keys to learn more.

If you have not created a cardholder yet, you’ll need one for the API endpoints listed in this document. See Creating test cardholders to learn more.

Each cardholder needs to have a card, and you’ll need their card ID to manage transactions. If you don’t have the card ID and you created a cardholder via the Core API, you can retrieve the card ID from the response body of a GET request to the /cardholders/{cardholder_id} endpoint. Or you can log into the Developer Dashboard, select Cards, and find the Card ID value.

Understanding transaction types#

Each transaction you create will have a transaction type, used to signify the nature of the transaction created. The transaction type affects whether this creates a debit or credit of funds.

Possible type values are:

  • purchase
  • withdrawal
  • return

At this time, we are unable to simulate a reversal.

Understanding processing types#

Each transaction also has a processing_type, which is one of:

  • authorization_request
  • financial_request
  • financial_advice

Authorization request - create a temporary hold on a card. The amount adjusts the cardholder's balance, but does not affect settlement. It is just securing the funds on the balance in case the merchant later sends a settlement message. An authorization request can be declined by the cardholder's balance. In production, this is a synchronous API call that is time sensitive. Authorization requests are usually automatically released within three working days, and they should never exist beyond one month.

Financial request - similar to authorization request actions, these do not need to adjust the amount or need to create a temporary hold. This means that the card networks will claim these funds during the following day’s settlement.

Financial advice - otherwise known as force posts, these create a transaction without a previous hold having been made on the account. These are rare scenarios, and are not time-sensitive transactions. If they induce a negative balance situation, they are usually resolved with the cardholder or by disputing the transaction with the networks. Apto cannot decline these messages.

Add funds to a card#

Now that you have a card set up, you’ll need to ensure your card has funds to draw from. At this time, you cannot transfer funds from a program balance to a card. For this walkthrough, you will work around this constraint and add funds to the card by refunding money to the card. Note: This workaround is a sandbox-only function that will not work in production.

To add funds to a card, submit a POST request to the /cards/{card_id}/transactions endpoint.

Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Billing amount: 105.33. This defines how much will be refunded to the card.
  • Processing type: financial_advice. Apto cannot decline this processing type.
  • Type: return. This means the transaction is a return.

Request

POST https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions

{
"billing_amount": 105.33,
"processing_type": "financial_advice",
"type": "return",
"description": "Test"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_f8332b818575e541",
"authorizations": [],
"adjustments": [
{
"adjustment": {
"id": "adj_6e09914dac06fdc2",
"created_at": "2020-11-19T19:13:35Z",
"local_amount": {
"amount": 105.33,
"currency": "USD"
},
"billing_amount": {
"amount": 105.33,
"currency": "USD"
},
"native_amount": {
"amount": 105.33,
"currency": "USD"
},
"native_fee_amount": {
"amount": 0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "refund"
}
}
],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T19:13:35Z",
"settlement_date": "2020-11-20T00:00:00Z",
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "complete",
"context": "Return (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": null,
"decline_code": null,
"funding_source_name": "Brent's Account (USD)",
"type": "REFUND",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": 105.33
},
"hold_amount": {
"currency": "USD",
"amount": 0.0
},
"cashback_amount": {
"currency": "USD",
"amount": 0.0
},
"fee_amount": {
"currency": "USD",
"amount": 0.0
},
"billing_amount": {
"currency": "USD",
"amount": 105.33
},
"native_balance_amount": {
"currency": "USD",
"amount": 105.33
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_d7f5401a3a723586",
"created_at": "2020-11-19T19:13:35.701Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

You have successfully added funds to the card. In our case, the card balance is $105.33.

Check the card balance#

To verify the card’s balance, submit a GET request to the /cards/{card_id} endpoint. Our example uses a card ID of crd_235ec5ec0032c815.

Request

GET https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815

Response

{
"card": {
"id": "crd_235ec5ec0032c815",
"design_key": null,
"livemode": true,
"wallets": [],
"program_id": "aptoeric02_sbx",
"last_four": "6345",
"status": "ACTIVATED",
"activated_at": "2020-11-19T19:09:31Z",
"created_at": "2020-11-19T19:09:31Z",
"issued_at": null,
"shipped_at": null,
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"network": "MASTERCARD",
"ledge_account_id": null,
"ordered_status": "ORDERED",
"allow_set_pin": true,
"allow_get_pin": false,
"program_profile_id": "aptoeric02_sbx",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"dda_number": null,
"aba_routing_number": null,
"wait_list": false,
"name_on_card": "BRENT JONES",
"allow_international": true,
"balance_id": "bal_5d6fb29d10c44d64",
"corporation_id": null,
"spendable_today": {
"amount": 105.33,
"currency": "USD",
"native_amount": 105.33,
"native_currency": "USD"
},
"spendable_balance": {
"amount": 105.33,
"currency": "USD",
"native_amount": 105.33,
"native_currency": "USD"
},
"total_balance": {
"amount": 105.33,
"currency": "USD",
"native_amount": 105.33,
"native_currency": "USD"
},
"additional_fields": [],
"event": null
}
}

The response shows the total balance available on the card. In our case, the response shows a total balance of $105.33. Now we’re ready to start making purchases.

The rest of this document is split between two kinds of transaction scenarios:

Since the single transaction message auth and capture scenario is simpler, we’ll start there.

Authorization and capture in a single message#

In this section, we look at transactions where authorization and capture are attempted with a single transaction message. These are transaction requests where the processing_type is financial_request. The following two examples show a declined request and an approved request.

Creating card transactions is a sandbox-only function that will not work in production.

Financial request declined#

If a cardholder tries to spend more money than they have, their request will be declined due to insufficient funds.

Submit a POST request to the /cards/{card_id}/transactions endpoint with a billing amount greater than the card balance.

We’ll attempt to spend almost a thousand dollars, which exceeds our total balance. Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Billing amount: 999.34. This defines how much we will attempt to spend.
  • Processing type: financial_request. This type of transaction contains both the authorization and the capture of funds simultaneously.
  • Type: purchase. This means the transaction is a purchase.

Request

POST https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions

{
"billing_amount": 999.34,
"processing_type": "financial_request",
"type": "purchase",
"description": "Test"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_724ce490de1a54e1",
"authorizations": [
{
"authorization": {
"id": "auth_4801faf4602d0705",
"issuer_data": null,
"decline_code": "decline_nsf",
"decline_reason": "INSUFFICIENT FUNDS",
"external_authorization_id": null,
"authorized": false,
"created_at": "2020-11-19T19:57:47Z"
}
}
],
"adjustments": [],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T19:57:47Z",
"settlement_date": null,
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "declined",
"context": "Decline. Insufficient funds. (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": "Insufficient Funds",
"decline_code": "decline_nsf",
"funding_source_name": "Brent's Account (USD)",
"type": "DECLINE",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -999.34
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -0.0
},
"native_balance_amount": {
"currency": null,
"amount": null
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_6112c4e4266ca8a6",
"created_at": "2020-11-19T19:57:48.212Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

The authorization request was declined due to insufficient funds on the card, as indicated by the decline_reason.

Financial request approved and cleared#

When a cardholder makes a financial request with a transaction amount less than the card balance, the transaction can be approved. In other words, there’s enough money on the card to make the purchase.

Submit a POST request to the /cards/{card_id}/transactions endpoint with a billing amount less than the card balance.

Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Billing amount: 8.12. This defines the amount of the purchase, and we know that we have $105.33 on the card from checking our balance earlier.
  • Processing type: financial_request. This type of transaction contains both the authorization and the capture of funds simultaneously.
  • Type: purchase. This means the transaction is a purchase.

Request

POST https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions

{
"billing_amount": 8.12,
"processing_type": "financial_request",
"type": "purchase",
"description": "Test"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_eb5273a61f9e1354",
"authorizations": [
{
"authorization": {
"id": "auth_3f825a465342cbe3",
"issuer_data": null,
"decline_code": null,
"decline_reason": null,
"external_authorization_id": null,
"authorized": true,
"created_at": "2020-11-19T20:00:05Z"
}
}
],
"adjustments": [
{
"adjustment": {
"id": "adj_d557583a99004fbc",
"created_at": "2020-11-19T20:00:05Z",
"local_amount": {
"amount": -8.12,
"currency": "USD"
},
"billing_amount": {
"amount": -8.12,
"currency": "USD"
},
"native_amount": {
"amount": -8.12,
"currency": "USD"
},
"native_fee_amount": {
"amount": -0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "capture"
}
}
],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T20:00:05Z",
"settlement_date": "2020-11-20T00:00:00Z",
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "complete",
"context": "PIN purchase (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": null,
"decline_code": null,
"funding_source_name": "Brent's Account (USD)",
"type": "PIN_PURCHASE",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -8.12
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -8.12
},
"native_balance_amount": {
"currency": "USD",
"amount": -8.12
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_d321d11136def30c",
"created_at": "2020-11-19T20:00:05.516Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

Notice the authorization says "authorized": true and the transaction state is complete, which shows that the authorization and capture occurred in a single message.

Authorization and capture as separate messages#

In this section, we look at transactions where one or more separate authorizations are made before capture. These are transaction requests where the processing_type is authorization_request. We’ll see a declined request and a few approved requests.

To simulate these scenarios, we’ll make multiple API calls for each transaction. Each time, the first API call represents a merchant requesting approval to authorize a hold for a specified amount. A subsequent API call represents the merchant confirmation of the final amount, which can be more than, equal to, or less than the held amount. \

Creating card transactions is a sandbox-only function that will not work in production.

Authorization request declined#

If a cardholder tries to spend more money than they have, their request will be declined due to insufficient funds.

Submit a POST request to the /cards/{card_id}/transactions endpoint with a billing amount greater than the card balance.

We’ll attempt to spend almost a thousand dollars, which exceeds our total balance. Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Billing amount: 999.34. This defines how much we will attempt to spend.
  • Processing type: authorization_request. This type of transaction contains the request to place a hold on the funds.
  • Type: purchase. This means the transaction is a purchase.

Because our request will be declined, we will not send a second API call for the capture.

Request

POST https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions

{
"billing_amount": 999.34,
"processing_type": "authorization_request",
"type": "purchase",
"description": "Test"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_36184447efaf9a93",
"authorizations": [
{
"authorization": {
"id": "auth_43580b7d84fbd3a3",
"issuer_data": null,
"decline_code": "decline_nsf",
"decline_reason": "INSUFFICIENT FUNDS",
"external_authorization_id": null,
"authorized": false,
"created_at": "2020-11-19T19:35:20Z"
}
}
],
"adjustments": [],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T19:35:20Z",
"settlement_date": null,
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "declined",
"context": "Decline. Insufficient funds. (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": "Insufficient Funds",
"decline_code": "decline_nsf",
"funding_source_name": "Brent's Account (USD)",
"type": "DECLINE",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -999.34
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -0.0
},
"native_balance_amount": {
"currency": null,
"amount": null
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_286c7ea2160dc843",
"created_at": "2020-11-19T19:35:21.156Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

The authorization request was declined due to insufficient funds on the card, as indicated by the decline_reason.

Authorization request cleared, equal to the pending amount#

In a multi-message authorization and capture process, the merchant requests an authorization for a purchase but keeps the option to change the amount. The final amount is sometimes the same as the original authorization request. For example, you might see a transaction like this when you deny a retailer’s request to “round up” your purchase amount to donate to a charity.

Submit a POST request to the /cards/{card_id}/transactions endpoint with a billing amount less than the card balance. When the request is approved, note the transaction ID in the response. You’ll need it to update the transaction with the final purchase amount. The approved request will have a state of pending.

Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Billing amount: 10.15. This defines the amount of the purchase, and we know that we have enough on the card from checking our balance earlier.
  • Processing type: authorization_request. This type of transaction contains the request to place a hold on the funds.
  • Type: purchase. This means the transaction is a purchase.

Request

POST https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions

{
"billing_amount": 10.15,
"processing_type": "authorization_request",
"type": "purchase",
"description": "Test"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_d9ab131480f8ff34",
"authorizations": [
{
"authorization": {
"id": "auth_5edc22f5e5241314",
"issuer_data": null,
"decline_code": null,
"decline_reason": null,
"external_authorization_id": null,
"authorized": true,
"created_at": "2020-11-19T21:50:16Z"
}
}
],
"adjustments": [
{
"adjustment": {
"id": "adj_a843a8e498b28766",
"created_at": "2020-11-19T21:50:16Z",
"local_amount": {
"amount": -10.15,
"currency": "USD"
},
"billing_amount": {
"amount": -10.15,
"currency": "USD"
},
"native_amount": {
"amount": -10.15,
"currency": "USD"
},
"native_fee_amount": {
"amount": -0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "capture"
}
}
],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T21:50:16Z",
"settlement_date": null,
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "pending",
"context": "Authorization (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": null,
"decline_code": null,
"funding_source_name": "Brent's Account (USD)",
"type": "PENDING",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -10.15
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -10.15
},
"native_balance_amount": {
"currency": "USD",
"amount": -10.15
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_f1e0a13067330765",
"created_at": "2020-11-19T21:50:16.971Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

Notice the state is pending. You can now complete the previously authorized transaction, informing the issuer of the final amount. In this case, the cleared transaction should equal the original authorized amount.

Submit a PUT request to the /cards/{card_id}/transactions/{transaction_id} endpoint with a billing amount equal to the original authorized amount.

Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Transaction ID: txn_d9ab131480f8ff34. This was provided in the earlier response.
  • Billing amount: 10.15. This defines the final amount of the purchase, which is the same amount originally authorized.
  • Processing type: financial_advice. This cannot be declined because it was previously authorized.

Request

PUT https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions/txn_d9ab131480f8ff34

{
"billing_amount": 10.15,
"processing_type": "financial_advice"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_d9ab131480f8ff34",
"authorizations": [
{
"authorization": {
"id": "auth_5edc22f5e5241314",
"issuer_data": null,
"decline_code": null,
"decline_reason": null,
"external_authorization_id": null,
"authorized": true,
"created_at": "2020-11-19T21:50:16Z"
}
}
],
"adjustments": [
{
"adjustment": {
"id": "adj_a843a8e498b28766",
"created_at": "2020-11-19T21:50:16Z",
"local_amount": {
"amount": -10.15,
"currency": "USD"
},
"billing_amount": {
"amount": -10.15,
"currency": "USD"
},
"native_amount": {
"amount": -10.15,
"currency": "USD"
},
"native_fee_amount": {
"amount": -0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "capture"
}
}
],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T21:50:16Z",
"settlement_date": "2020-11-20T00:00:00Z",
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "complete",
"context": "Standard purchase (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": null,
"decline_code": null,
"funding_source_name": "Brent's Account (USD)",
"type": "PURCHASE",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -10.15
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -10.15
},
"native_balance_amount": {
"currency": "USD",
"amount": -10.15
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_bd32d71ad1911048",
"created_at": "2020-11-19T21:53:58.385Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

Notice the response includes "state": "complete". This completes the transaction.

Authorization request cleared, less than the pending amount#

In a multi-message authorization and capture process, the merchant requests an authorization for a purchase but keeps the option to change the amount. The final amount is sometimes less than the original authorization request. For example, you might see a transaction like this when you buy fuel from a gas station.

Submit a POST request to the /cards/{card_id}/transactions endpoint with a billing amount less than the card balance. When the request is approved, note the transaction ID in the response. You’ll need it to update the transaction with the final purchase amount. The approved request will have a state of pending.

Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Billing amount: 12.34. This defines the amount of the purchase, and we know that we have enough on the card from checking our balance earlier.
  • Processing type: authorization_request. This type of transaction contains the request to place a hold on the funds.
  • Type: purchase. This means the transaction is a purchase.

Request

POST https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions

{
"billing_amount": 12.34,
"processing_type": "authorization_request",
"type": "purchase",
"description": "Test"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_93879ffb2b5c14a8",
"authorizations": [
{
"authorization": {
"id": "auth_3ab56a72a41a30e1",
"issuer_data": null,
"decline_code": null,
"decline_reason": null,
"external_authorization_id": null,
"authorized": true,
"created_at": "2020-11-19T19:44:23Z"
}
}
],
"adjustments": [
{
"adjustment": {
"id": "adj_66556b71ce1d908c",
"created_at": "2020-11-19T19:44:23Z",
"local_amount": {
"amount": -12.34,
"currency": "USD"
},
"billing_amount": {
"amount": -12.34,
"currency": "USD"
},
"native_amount": {
"amount": -12.34,
"currency": "USD"
},
"native_fee_amount": {
"amount": -0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "capture"
}
}
],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T19:44:23Z",
"settlement_date": null,
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "pending",
"context": "Authorization (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": null,
"decline_code": null,
"funding_source_name": "Brent's Account (USD)",
"type": "PENDING",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -12.34
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -12.34
},
"native_balance_amount": {
"currency": "USD",
"amount": -12.34
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_0a4807f384bbf2a4",
"created_at": "2020-11-19T19:44:23.589Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

Notice the state is pending. You can now complete the previously authorized transaction, informing the issuer of the final amount. In this case, the cleared transaction is less than the original authorized amount.

Submit a PUT request to the /cards/{card_id}/transactions/{transaction_id} endpoint with a billing amount less than the original authorized amount.

Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Transaction ID: txn_93879ffb2b5c14a8. This was provided in the earlier response.
  • Billing amount: 12.00. This defines the final amount of the purchase, which is less than the amount originally authorized.
  • Processing type: financial_advice. This cannot be declined because it was previously authorized.

Request

PUT https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions/txn_93879ffb2b5c14a8

{
"billing_amount": 12.0,
"processing_type": "financial_advice"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_93879ffb2b5c14a8",
"authorizations": [
{
"authorization": {
"id": "auth_3ab56a72a41a30e1",
"issuer_data": null,
"decline_code": null,
"decline_reason": null,
"external_authorization_id": null,
"authorized": true,
"created_at": "2020-11-19T19:44:23Z"
}
}
],
"adjustments": [
{
"adjustment": {
"id": "adj_5e1cfe1020273b50",
"created_at": "2020-11-19T19:53:47Z",
"local_amount": {
"amount": 0.34,
"currency": "USD"
},
"billing_amount": {
"amount": 0.34,
"currency": "USD"
},
"native_amount": {
"amount": 0.34,
"currency": "USD"
},
"native_fee_amount": {
"amount": 0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "refund"
}
},
{
"adjustment": {
"id": "adj_66556b71ce1d908c",
"created_at": "2020-11-19T19:44:23Z",
"local_amount": {
"amount": -12.34,
"currency": "USD"
},
"billing_amount": {
"amount": -12.34,
"currency": "USD"
},
"native_amount": {
"amount": -12.34,
"currency": "USD"
},
"native_fee_amount": {
"amount": -0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "capture"
}
}
],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T19:44:23Z",
"settlement_date": "2020-11-20T00:00:00Z",
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "complete",
"context": "Standard purchase (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": null,
"decline_code": null,
"funding_source_name": "Brent's Account (USD)",
"type": "PURCHASE",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -12.0
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -12.0
},
"native_balance_amount": {
"currency": "USD",
"amount": -12.0
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_b964d30e08fdbdd6",
"created_at": "2020-11-19T19:53:48.048Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

Notice the response includes "state": "complete". This completes the transaction.

Authorization request cleared, greater than the pending amount#

In a multi-message authorization and capture process, the merchant requests an authorization for a purchase but keeps the option to change the amount. The final amount is sometimes greater than the original authorization request. For example, you might see a transaction like this when you buy a meal at a restaurant and leave a tip.

Submit a POST request to the /cards/{card_id}/transactions endpoint with a billing amount less than the card balance. When the request is approved, note the transaction ID in the response. You’ll need it to update the transaction with the final purchase amount. The approved request will have a state of pending.

Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Billing amount: 21.22. This defines the amount of the purchase, and we know that we have enough on the card from checking our balance earlier.
  • Processing type: authorization_request. This type of transaction contains the request to place a hold on the funds.
  • Type: purchase. This means the transaction is a purchase.

Request

POST https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions

{
"billing_amount": 21.22,
"processing_type": "authorization_request",
"type": "purchase",
"description": "Test"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_bfd3c936c0b73868",
"authorizations": [
{
"authorization": {
"id": "auth_b000954a184af8dc",
"issuer_data": null,
"decline_code": null,
"decline_reason": null,
"external_authorization_id": null,
"authorized": true,
"created_at": "2020-11-19T22:09:57Z"
}
}
],
"adjustments": [
{
"adjustment": {
"id": "adj_f8c058d5ff3cec35",
"created_at": "2020-11-19T22:09:57Z",
"local_amount": {
"amount": -21.22,
"currency": "USD"
},
"billing_amount": {
"amount": -21.22,
"currency": "USD"
},
"native_amount": {
"amount": -21.22,
"currency": "USD"
},
"native_fee_amount": {
"amount": -0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "capture"
}
}
],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T22:09:57Z",
"settlement_date": null,
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "pending",
"context": "Authorization (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": null,
"decline_code": null,
"funding_source_name": "Brent's Account (USD)",
"type": "PENDING",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -21.22
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -21.22
},
"native_balance_amount": {
"currency": "USD",
"amount": -21.22
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_bf8e8d12ea61c532",
"created_at": "2020-11-19T22:09:58.048Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

Notice the state is pending. You can now complete the previously authorized transaction, informing the issuer of the final amount. In this case, the cleared transaction is greater than the original authorized amount.

Submit a PUT request to the /cards/{card_id}/transactions/{transaction_id} endpoint with a billing amount greater than the original authorized amount.

Our example uses the following information:

  • Card ID: crd_235ec5ec0032c815. This identifies the card where the funds will be added.
  • Transaction ID: txn_bfd3c936c0b73868. This was provided in the earlier response.
  • Billing amount: 25.00. This defines the final amount of the purchase, which is greater than the amount originally authorized.
  • Processing type: financial_advice. This cannot be declined because it was previously authorized.

Request

PUT https://api.sbx.aptopayments.com/cards/crd_235ec5ec0032c815/transactions/txn_bfd3c936c0b73868

{
"billing_amount": 25.0,
"processing_type": "financial_advice"
}

Response

{
"transaction": {
"livemode": true,
"id": "txn_bfd3c936c0b73868",
"authorizations": [
{
"authorization": {
"id": "auth_b000954a184af8dc",
"issuer_data": null,
"decline_code": null,
"decline_reason": null,
"external_authorization_id": null,
"authorized": true,
"created_at": "2020-11-19T22:09:57Z"
}
}
],
"adjustments": [
{
"adjustment": {
"id": "adj_4d0f71c3fef01b4c",
"created_at": "2020-11-19T22:14:01Z",
"local_amount": {
"amount": -3.78,
"currency": "USD"
},
"billing_amount": {
"amount": -3.78,
"currency": "USD"
},
"native_amount": {
"amount": -3.78,
"currency": "USD"
},
"native_fee_amount": {
"amount": -0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "capture"
}
},
{
"adjustment": {
"id": "adj_f8c058d5ff3cec35",
"created_at": "2020-11-19T22:09:57Z",
"local_amount": {
"amount": -21.22,
"currency": "USD"
},
"billing_amount": {
"amount": -21.22,
"currency": "USD"
},
"native_amount": {
"amount": -21.22,
"currency": "USD"
},
"native_fee_amount": {
"amount": -0.0,
"currency": "USD"
},
"funding_source_transaction_id": null,
"funding_source_name": "",
"exchange_rate": 1.0,
"type": "capture"
}
}
],
"cardholder_id": "crdhldr_552ba4bd292ba1039909",
"created_at": "2020-11-19T22:09:57Z",
"settlement_date": "2020-11-20T00:00:00Z",
"cardholder_email": "eric+3@aptopayments.com",
"cardholder_first_name": "Brent",
"cardholder_last_name": "Jones",
"card_id": "crd_235ec5ec0032c815",
"corporation_id": null,
"description": "AptoEric02_SBX Test USA",
"merchant_name": "AptoEric02_SBX Test",
"merchant_locality": "",
"merchant_region": "",
"merchant_country": "USA",
"mcc": "7299",
"mcc_icon": "finance",
"mcc_name": null,
"merchant_identifier": null,
"merchant_terminal_identifier": null,
"state": "complete",
"context": "Standard purchase (SHIFT)",
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "SHIFT",
"shift_stand_in": false,
"dispute_id": null,
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null,
"decline_reason": null,
"decline_code": null,
"funding_source_name": "Brent's Account (USD)",
"type": "PURCHASE",
"merchant": {
"found": false,
"latitude": null,
"longitude": null,
"name": null,
"formatted_address": null,
"street_number": null,
"street": null,
"locality": null,
"region": null,
"country": null,
"postal_code": null,
"external_id": null
},
"idempotency_key": null,
"local_amount": {
"currency": "USD",
"amount": -25.0
},
"hold_amount": {
"currency": "USD",
"amount": -0.0
},
"cashback_amount": {
"currency": "USD",
"amount": -0.0
},
"fee_amount": {
"currency": "USD",
"amount": -0.0
},
"billing_amount": {
"currency": "USD",
"amount": -25.0
},
"native_balance_amount": {
"currency": "USD",
"amount": -25.0
},
"event": null
}
}

Webhook

{
"event": {
"id": "event_886f443ce75b823c",
"created_at": "2020-11-19T22:14:01.123Z",
"event_type": "transaction_update",
"data_type": "transaction",
"data": {
Same as response body
}
}
}

Notice the response includes "state": "complete". This completes the transaction.