ACH (eCheck) Direct Debit

ACH (also called eCheck) Direct Debit enables you to directly debit a buyers bank account.

In compliance with NACHA’s bank account validation rule, before proceeding with any eCheck transactions Finix automatically validates a bank account the first time it's being used, or after a change has been made. If the bank account is flagged as invalid, the transaction is blocked. This helps prevent fraud and decreases the chances of an eCheck return.

The following values get returned for bank_account_validation_check:

  • NOT_ATTEMPTED: Default value for new bank accounts that haven’t been validated yet.
  • VALID: Bank account was found to be open and accepts eCheck.
  • INVALID: Could not validate bank account was valid. Creating an eCheck with a bank account that’s marked as INVALID will result in a failure. Please reach out to the bank account holder for a new form of payment.
  • INCONCLUSIVE: Bank account validation was inconclusive. Bank accounts that are marked as INCONCLUSIVE will be allowed to create an eCheck.

ACH transactions can get rejected for up to sixty days for a variety of reasons including insufficient funds, closed accounts, or a revoked authorization (i.e. dispute). Because of the 60 day threshold, Finix can configure a delay in the settling of an eCheck.

For example, your application can implement a six day delay to give the buyer more time and feel more confident that the eCheck will not be rejected. To configure this delay, reach out to your Finix point of contact or email Finix support.

Creating an ACH (eCheck) Sale

First create a Payment Instrument to represent your buyers bank account.

  • Use Finix Hosted Fields to collect the buyers bank account details and other payment information.
warning

You must create another Identity for your buyer separate from the merchant Identity. Associate the buyer Identity with the bank account you tokenize.

Create a transfer with the Payment Instrument you created to debit funds directly from the buyers bank account.

Copy
Copied
curl https://finix.sandbox-payments-api.com/transfers \
    -H "Content-Type: application/vnd.json+api" \
    -H 'Finix-Version:2022-02-01' \
    -u  USsRhsHYZGBPnQw8CByJyEQW:8a14c2f9-d94b-4c72-8f5c-a62908e5b30e \
    -d '{
	    "fee": 603,
	    "currency": "USD",
	    "merchant": "MUeDVrf2ahuKc9Eg5TeZugvs",
	    "tags": {
	        "order_number": "21DFASJSAKAS"
	    },
	    "source": "PIr1Ru7ewBkEYVVn7SP1u5FW",
	    "amount": 6031
	}'

Direct debit transfers return a response with type DEBIT.

  • When a reversal or return gets processed a transfer with type REVERSAL and a subtype SYSTEM is automatically created and subtracts the amount from the future settlement.

Example Response:

Copy
Copied
{
  "id" : "TRoom5emPxiP1TRAmHcSjHgz",
  "amount" : 6031,
  "tags" : {
    "order_number" : "21DFASJSAKAS"
  },
  "state" : "PENDING",
  "trace_id" : "0156ff8f-88c1-4090-8eb6-9f33218b0ec5",
  "currency" : "USD",
  "application" : "APgPDQrLD52TYvqazjHJJchM",
  "source" : "PIr1Ru7ewBkEYVVn7SP1u5FW",
  "destination" : null,
  "ready_to_settle_at" : null,
  "externally_funded" : "UNKNOWN",
  "fee" : 603,
  "statement_descriptor" : "FNX*FINIX FLOWERS",
  "type" : "DEBIT",
  "messages" : [ ],
  "raw" : null,
  "created_at" : "2022-09-01T20:36:08.13Z",
  "updated_at" : "2022-09-01T20:36:09.42Z",
  "idempotency_id" : null,
  "merchant_identity" : "IDuqZpDw28f2KK6YuDk4jNLg",
  "subtype" : "API",
  "failure_code" : null,
  "failure_message" : null,
  "additional_buyer_charges" : null,
  "_links" : {
    "application" : {
      "href" : "https://finix.sandbox-payments-api.com/applications/APgPDQrLD52TYvqazjHJJchM"
    },
    "self" : {
      "href" : "https://finix.sandbox-payments-api.com/transfers/TRoom5emPxiP1TRAmHcSjHgz"
    },
    "merchant_identity" : {
      "href" : "https://finix.sandbox-payments-api.com/identities/IDuqZpDw28f2KK6YuDk4jNLg"
    },
    "payment_instruments" : {
      "href" : "https://finix.sandbox-payments-api.com/transfers/TRoom5emPxiP1TRAmHcSjHgz/payment_instruments"
    },
    "reversals" : {
      "href" : "https://finix.sandbox-payments-api.com/transfers/TRoom5emPxiP1TRAmHcSjHgz/reversals"
    },
    "fees" : {
      "href" : "https://finix.sandbox-payments-api.com/transfers/TRoom5emPxiP1TRAmHcSjHgz/fees"
    },
    "disputes" : {
      "href" : "https://finix.sandbox-payments-api.com/transfers/TRoom5emPxiP1TRAmHcSjHgz/disputes"
    },
    "source" : {
      "href" : "https://finix.sandbox-payments-api.com/payment_instruments/PIr1Ru7ewBkEYVVn7SP1u5FW"
    },
    "fee_profile" : {
      "href" : "https://finix.sandbox-payments-api.com/fee_profiles/FPvCQUcnsueN3Bc3zR1qCBG8"
    }
  }
}

Like other transfers, the response will get updated (usually within an hour) with a timestamp of when the transfer will be ready_to_settle_at and get included in the next Settlement that closes for the Merchant.

You'll also receive a webhook created event with entity transfer.

Example ACH (eCheck) Transfer Created
Copy
Copied
{
  "type": "created",
  "entity": "transfer",
  "occurred_at": "2022-09-01T20:36:20.588717",
  "_embedded": {
    "transfers": [
      {
        "idempotency_id": null,
        "amount": 6031,
        "trace_id": "0156ff8f-88c1-4090-8eb6-9f33218b0ec5",
        "failure_code": null,
        "fee": 603,
        "destination": null,
        "raw": null,
        "created_at": "2022-09-01T20:36:08.13Z",
        "source": "PIr1Ru7ewBkEYVVn7SP1u5FW",
        "merchant_identity": "IDuqZpDw28f2KK6YuDk4jNLg",
        "failure_message": null,
        "type": "DEBIT",
        "tags": {
          "order_number": "21DFASJSAKAS"
        },
        "statement_descriptor": "FNX*FINIX FLOWERS",
        "additional_buyer_charges": null,
        "ready_to_settle_at": null,
        "application": "APgPDQrLD52TYvqazjHJJchM",
        "updated_at": "2022-09-01T20:36:08.69Z",
        "subtype": "API",
        "externally_funded": "UNKNOWN",
        "messages": [],
        "currency": "USD",
        "id": "TRoom5emPxiP1TRAmHcSjHgz",
        "state": "PENDING"
      }
    ]
  }
}

You'll also receive a webhook created event with entity transfer.

Example ACH (eCheck) Transfer Created
Copy
Copied
{
  "type": "created",
  "entity": "transfer",
  "occurred_at": "2022-09-01T20:36:20.588717",
  "_embedded": {
    "transfers": [
      {
        "idempotency_id": null,
        "amount": 6031,
        "trace_id": "0156ff8f-88c1-4090-8eb6-9f33218b0ec5",
        "failure_code": null,
        "fee": 603,
        "destination": null,
        "raw": null,
        "created_at": "2022-09-01T20:36:08.13Z",
        "source": "PIr1Ru7ewBkEYVVn7SP1u5FW",
        "merchant_identity": "IDuqZpDw28f2KK6YuDk4jNLg",
        "failure_message": null,
        "type": "DEBIT",
        "tags": {
          "order_number": "21DFASJSAKAS"
        },
        "statement_descriptor": "FNX*FINIX FLOWERS",
        "additional_buyer_charges": null,
        "ready_to_settle_at": null,
        "application": "APgPDQrLD52TYvqazjHJJchM",
        "updated_at": "2022-09-01T20:36:08.69Z",
        "subtype": "API",
        "externally_funded": "UNKNOWN",
        "messages": [],
        "currency": "USD",
        "id": "TRoom5emPxiP1TRAmHcSjHgz",
        "state": "PENDING"
      }
    ]
  }
}

For more information, see Paying our Transfers.

Refunding or Reversing an ACH (eCheck) Sale

Reversing an ACH (eCheck) debit is similar to reversing a transfer.

To refund an ACH (eCheck) debit, create a transfer reversal using the id of the original ACH (eCheck) debit transfer that you want to reverse.

Copy
Copied
curl https://finix.sandbox-payments-api.com/transfers/TRuR4hKLpum9ALvPv9ZpNuFA/reversals \
    -H "Content-Type: application/vnd.json+api" \
    -u  USsRhsHYZGBPnQw8CByJyEQW:8a14c2f9-d94b-4c72-8f5c-a62908e5b30e \
    -d  '
  {
  "refund_amount" : 6031,
  "tags" : {
      "test" : "refund"
    }
  }'

A successful response returns 201 and the newly created transfer with type REVERSAL.

Copy
Copied
{
  "id" : "TR3K7CdXeHyqjaeofubVN2fm",
  "amount" : 6031,
  "tags" : {
    "test" : "refund"
  },
  "state" : "PENDING",
  "trace_id" : "73b43a34-04ff-4d0f-9b2d-628434f77248",
  "currency" : "USD",
  "application" : "APgPDQrLD52TYvqazjHJJchM",
  "source" : null,
  "destination" : "PIr1Ru7ewBkEYVVn7SP1u5FW",
  "ready_to_settle_at" : null,
  "externally_funded" : "UNKNOWN",
  "fee" : 0,
  "statement_descriptor" : "FNX*FINIX FLOWERS",
  "type" : "REVERSAL",
  "messages" : [ ],
  "raw" : null,
  "created_at" : "2022-05-12T13:36:43.23Z",
  "updated_at" : "2022-05-12T13:36:43.45Z",
  "idempotency_id" : null,
  "merchant_identity" : "IDuqZpDw28f2KK6YuDk4jNLg",
  "subtype" : "API",
  "_links" : {
    "application" : {
      "href" : "https://finix.sandbox-payments-api.com/applications/APgPDQrLD52TYvqazjHJJchM"
    },
    "self" : {
      "href" : "https://finix.sandbox-payments-api.com/transfers/TR3K7CdXeHyqjaeofubVN2fm"
    },
    "parent" : {
      "href" : "https://finix.sandbox-payments-api.com/transfers/TRacB6Q6GcW6yvFUKawSnMEP"
    },
    "destination" : {
      "href" : "https://finix.sandbox-payments-api.com/payment_instruments/PIe2YvpcjvoVJ6PzoRPBK137"
    },
    "merchant_identity" : {
      "href" : "https://finix.sandbox-payments-api.com/identities/IDuqZpDw28f2KK6YuDk4jNLg"
    },
    "payment_instruments" : {
      "href" : "https://finix.sandbox-payments-api.com/transfers/TR3K7CdXeHyqjaeofubVN2fm/payment_instruments"
    },
    "fee_profile" : {
      "href" : "https://finix.sandbox-payments-api.com/fee_profiles/FPvCQUcnsueN3Bc3zR1qCBG8"
    }
  }
}

The state of the transfer reversal will update to SUCCEEDED when the reversal gets successfully processed. Buyers will see the refund returned as a credit within 5-10 business days, depending on their bank. ACH (eCheck) reversals can’t get canceled once processed.

Handling an ACH (eCheck) Return

An ACH (eCheck) gets returned when either the credited or debited bank account can't be found. Reasons an ACH (eCheck) could return includes a typo was made when the transfer was getting created, insufficient funds, or the bank account doesn't exist.

It can take anywhere from 2-5 days for an ACH (eCHeck) debit to get returned. When an ACH (eCheck) gets returned, you receive a webhook updated event with

  • entity - transfer
  • type - REVERSE
  • sub_type - PLATFORM_CREDIT

ACH (eCheck) returns appear on the Finix Dashboard as a REVERSAL on the Refunds tab.

Example ACH (eCheck) Return Webhook Event
Copy
Copied
{
  "type": "updated",
  "entity": "transfer",
  "occurred_at": "2022-09-01T20:49:23.437609",
  "_embedded": {
    "transfers": [
      {
        "idempotency_id": null,
        "amount": 6031,
        "trace_id": "0156ff8f-88c1-4090-8eb6-9f33218b0ec5",
        "failure_code": null,
        "fee": 603,
        "destination": null,
        "raw": null,
        "created_at": "2022-09-01T20:36:08.13Z",
        "source": "PIr1Ru7ewBkEYVVn7SP1u5FW",
        "merchant_identity": "IDuqZpDw28f2KK6YuDk4jNLg",
        "failure_message": null,
        "type": "REVERSE",
        "tags": {
          "order_number": "21DFASJSAKAS"
        },
        "statement_descriptor": "FNX*FINIX FLOWERS",
        "additional_buyer_charges": null,
        "ready_to_settle_at": null,
        "application": "APgPDQrLD52TYvqazjHJJchM",
        "updated_at": "2022-09-01T20:49:23.43",
        "subtype": "MERCHANT_CREDIT_ADJUSTMENT",
        "externally_funded": "UNKNOWN",
        "messages": [],
        "currency": "USD",
        "id": "TRoom5emPxiP1TRAmHcSjHgz",
        "state": "PENDING"
      }
    ]
  }
}

Handling an ACH (eCheck) Refund Return

Banks manage the ACH networks and often pre-fund transactions, before debiting funds from the buyers bank account.

When an ACH (eCheck) refund gets returned, two transfers get created to credit the funds back to the original bank account. The webhook events you receive, with subtype:

  • MERCHANTDEBITADJUSTMENT: one transfer to debit funds that were preemptively credited
  • PLATFORM_CREDIT one transfer to return the funds back to the original bank account.
Example ACH (eCheck) Merchant Debit
Copy
Copied
{
  "type": "updated",
  "entity": "transfer",xs
  "occurred_at": "2022-09-01T20:49:23.437609",
  "_embedded": {
    "transfers": [
      {
        "idempotency_id": null,
        "amount": 6031,
        "trace_id": "0156ff8f-88c1-4090-8eb6-9f33218b0ec5",
        "failure_code": null,
        "fee": 603,
        "destination": null,
        "raw": null,
        "created_at": "2022-09-01T20:36:08.13Z",
        "source": "PIr1Ru7ewBkEYVVn7SP1u5FW",
        "merchant_identity": "IDuqZpDw28f2KK6YuDk4jNLg",
        "failure_message": null,
        "type": "REVERSE",
        "tags": {
          "order_number": "21DFASJSAKAS"
        },
        "statement_descriptor": "FNX*FINIX FLOWERS",
        "additional_buyer_charges": null,
        "ready_to_settle_at": null,
        "application": "APgPDQrLD52TYvqazjHJJchM",
        "updated_at": "2022-09-01T20:49:23.43",
        "subtype": "MERCHANT_DEBIT_ADJUSTMENT",
        "externally_funded": "UNKNOWN",
        "messages": [],
        "currency": "USD",
        "id": "TRoom5emPxiP1TRAmHcSjHgz",
        "state": "PENDING"
      }
    ]
  }
}
Example ACH (eCheck) Platform Credit
Copy
Copied
{
  "type": "updated",
  "entity": "transfer",xs
  "occurred_at": "2022-09-01T20:49:23.437609",
  "_embedded": {
    "transfers": [
      {
        "idempotency_id": null,
        "amount": 6031,
        "trace_id": "0156ff8f-88c1-4090-8eb6-9f33218b0ec5",
        "failure_code": null,
        "fee": 603,
        "destination": null,
        "raw": null,
        "created_at": "2022-09-01T20:36:08.13Z",
        "source": "PIr1Ru7ewBkEYVVn7SP1u5FW",
        "merchant_identity": "IDuqZpDw28f2KK6YuDk4jNLg",
        "failure_message": null,
        "type": "REVERSE",
        "tags": {
          "order_number": "21DFASJSAKAS"
        },
        "statement_descriptor": "FNX*FINIX FLOWERS",
        "additional_buyer_charges": null,
        "ready_to_settle_at": null,
        "application": "APgPDQrLD52TYvqazjHJJchM",
        "updated_at": "2022-09-01T20:49:23.43",
        "subtype": "PLATFORM_CREDIT",
        "externally_funded": "UNKNOWN",
        "messages": [],
        "currency": "USD",
        "id": "TRoom5emPxiP1TRAmHcSjHgz",
        "state": "PENDING"
      }
    ]
  }
}