Pull from card

Instantly access money from your customers by pulling funds from their cards.

With pull from card transfers, Moov supports instant account funding and account-to-account transfers using supported Visa and Mastercard debit cards, available 24/7/365. Pull from card is available for customers that are chartered financial institutions.

Pull from card funds flow diagram
Pull from card is currently only available in test mode, or in a closed beta.

Use cases

Pull transfers, or account funding transactions, facilitate the movement of funds from a supported debit or prepaid card to an external account owned by the cardholder. These transactions are ideal for:

  • Initial account funding: Quickly deposit funds to newly opened accounts.
  • External transfers: Move money from accounts held at other financial institutions.

Currently, pull from card transactions cannot be used for peer-to-peer (P2P) transfers.

Within the Moov platform, this payment type is modeled as a transfer from an individual’s linked debit or prepaid card to the Moov wallet of the financial institution external account. When initiating a transaction, the following needs to be set:

  • Source: Individual’s debit or prepaid card (Visa and Mastercard only).
  • Destination: Financial institution’s Moov wallet.

The destination account requires the wallet and collect-funds capabilities.

Determine support for pull from card

Ensure you have linked a card on the account. The simplest way to securely link a card is by using the card link Drop, a prebuilt UI component for embedding card-based payments. If you’ve provided proof of PCI compliance, you also have the option to link a card using the POST link a card endpoint.

When linking a card, ensure that the Moov account is created with the same name as the cardholder’s name on the linked card. You will receive a 400 response during transfer creation if the names do not match.

Moov strongly recommends using the X-Wait-For header in the request to receive a synchronous response. This includes the rail response and newly created payment methods. If you omit the X-Wait-For header, you’ll get an asynchronous response and need to call the list payment methods GET endpoint. You can also subscribe to webhooks and wait for the new payment methods to be available for use.

Once you’ve linked a card, use the GET endpoint and check the domesticPullfromCard field in the response to see if pull-from-card is supported. The domesticPullfromCard field will show one of the following:

Eligibility Description
supported Funds will be available to the destination upon authorization
not-supported This card is ineligible for pull-from-card payments. Contact your issuer for more details
unknown Eligibility has not been checked or is unknown
1
2
curl -X GET "https://api.moov.io/accounts/{accountID}/cards" \
  -H 'Authorization: Bearer {token}' \
1
2
3
4
5
6
const moov = new Moov(credentialsObject);

const card = await moov.cards.get({
  accountID: "accountID",
  cardID: "cardID"
});
1
2
3
4
5
6
mc, _ := moov.NewClient()

var accountID string
var cardID string

mc.GetCard(ctx, accountID, cardID)

To prevent the risk of account takeover, Moov has taken steps to verify the card’s account ownership. The card verification process will match the existing cardVerification object’s addressLine1, postalCode, and cvv between the Moov account and the card network:

1
2
3
4
5
6
7
{
  "cardVerification": {
    "addressLine1": "match",
    "postalCode": "match",
    "cvv": "match"
  }
}

In addition, Moov supports Visa’s Account Name Inquiry (ANI). ANI ensures that the name provided on the linked card matches the name held on file with the issuer. This tool is optional and serves to enhance cardholder verification.

The card link POST endpoint and PATCH endpoint offer an optional verifyName field. To submit a name to Visa for verification, supply the holderName and set verifyName to true.

1
2
3
4
5
6
7
8
{
  "cardVerification": {
    "fullName": "match", // noMatch, match, partialMatch, notChecked
    "firstName": "match", // noMatch, match, partialMatch, notChecked
    "middleName": "noMatch", // noMatch, match, partialMatch, notChecked
    "lastName": "match" // noMatch, match, partialMatch, notChecked
  },
}

The verification process is crucial in reducing the risk of fraudulent activities and ensuring cards are linked to the rightful owner. If these requirements are not met, the card will be ineligible for pull from card transactions. You can find example name verification scenarios in our test mode guide.

Implement pull from card

You can simulate pull from card transfers in test mode using specific test cards.

The pull-from-card payment method becomes available when the following criteria are met:

  • The linked card is supported
  • The linked card meets verification requirements
  • Moov has approved the account for pull from card transfers

Initiate the transfer

A pull transfer can be created when the source is a sender with a linked card with the transfers capability and the destination is a Moov wallet with collect-funds capability.

In the response, check the domesticPullFromCard field to determine if the card supports pull from card transactions. Possible values are supported, not-supported, or unknown.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
curl -X GET "https://api.moov.io/transfers" \
  -H 'Authorization: Bearer {token}' \
  -H "Origin: https://api.moov.io" \
  -H "X-Wait-For: rail-response" \
  --data-raw '{
  "source": {
    # Pull from card
    "paymentMethodID": "UUID"
  },
  "destination": {
    # Moov wallet
    "paymentMethodID": "UUID"
  },
  "amount": {
    "value": 10000,
    "currency": "usd"
  },
  "description": "Account funding example"
}'\
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
const moov = new Moov(credentialsObject);

const transfer = await moov.transfers.create({
  source: {
    // Pull from card
    paymentMethodID: "UUID"
  },
  destination: {
    // Moov wallet
    paymentMethodID: "UUID"
  },
  amount: {
    value: 100,
    currency: "USD"
  },
  description: "Account funding example"
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mc, _ := moov.NewClient()

mc.CreateTransfer(ctx, moov.CreateTransfer{
  Amount: moov.Amount{
    Currency: "USD",
    Value:    97, // $0.97
  },
  Source: moov.CreateTransfer_Source{
    // Pull from card
    PaymentMethodID: "UUID",
    CardDetails: &moov.CreateTransfer_CardDetailsSource{
      DynamicDescriptor: "Pull transfer",
    },
  },
  Destination: moov.CreateTransfer_Destination{
    // Moov wallet
    PaymentMethodID: "UUID",
  },
  FacilitatorFee: moov.CreateTransfer_FacilitatorFee{
    Total: moov.PtrOf(int64(2)), // $0.02
  },
  Description: "Account funding example",
},)

Track transfer status

To track the transfer status, view cardDetails under the destination object from the transfers GET endpoint:

Status Description
initiated Transaction is created and awaiting authorization
failed Issuer declined or there was error with processing
completed Authorization request was successful and Issuer approved the transaction

Refund status

In the event of an error, pull from card transfers can be refunded. The table below lists the possible refund statuses.

Status Description
confirmed Authorization request was successful and the issuer has approved the transaction
pending The refund is in progress, but not yet completed
completed The card network has settled the transaction and the funds should be available in the customer’s account
failed Issuer declined, or there was error with processing

Set up recurring transfers

Using the transactionSource parameter in source.cardDetails to set up recurring payments. Mark the initial transaction as first-recurring and subsequent transactions as recurring.

1
2
3
4
5
6
7
8
{
  "source": {
    "cardDetails": {
      "dynamicDescriptor": "WhlBdy Monthly",
      "transactionSource": "first-recurring"
    },
  }
}
1
2
3
4
5
6
7
8
{
  "source": {
    "cardDetails": {
      "dynamicDescriptor": "WhlBdy Monthly",
      "transactionSource": "recurring"
    },
  }
}

For more details, see our recurring payments guide.

Transfer guidelines

When implementing pull from card transfers, be sure to follow the transfer limits defined below.

Error responses

You will receive an 400 error response if:

  • The transfer exceeds the amount limit ($10,000)
  • Your account is not enabled for the use case

If the transfer has exceeded the limit, you should retry the transfer with a lower amount. If you continue to have problems, please contact Moov so we can configure your account accordingly.

Velocity limits

There are limits on the amount a card fingerprint can send within a specified time. If you’ve exceeded these limits, pull from card will trigger a 400 error response of rejected-high-risk.

Limit type Maximum limit
Amount $10,000
1-day velocity $10,000
7-day velocity $25,000
30-day velocity $50,000

Disputes

You can receive notifications on disputes by subscribing to the dispute.created and dispute.updated webhook events. Alternatively, you can use the disputes list GET endpoint to pull a list of disputes on a recurring schedule.

For more details on the disputes lifecycle, see our disputes guide.

Summary Beta