Skip to main content

Verify Cards (Zero-Dollar Authorization)

Zero-dollar authorization allows you to verify a payment card is valid without charging the customer. This is useful when you want to validate card details before saving them, set up recurring payments, or confirm a card works before the first charge.

Common use cases include:

  • Adding cards to customer profiles - Validate card details before saving for future use
  • Setting up recurring payments - Verify the card works before initiating a subscription
  • Pre-order validation - Confirm card validity without immediate payment
  • Card-on-file updates - Verify a new card before replacing an existing one

Now that you have completed the Collect Cards guide, let's verify a card with a zero-dollar authorization.

Getting Started​

To get started, you will need a Credova Account.

Get your Secret Key​

Next you will need your Secret Key. Go to your Developers section and click Reveal for your Secret Key and copy the value.

Save the Secret Key as it will be used in the next steps of this guide.

Create a Verification Payment​

We will use the information from the previously collected card to create a verification payment.

For example, given you have a previously collected card:

{
"id": "card_AjkCFKAYiTsjghXWMzoXFPMxj",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "test",
"cardholder_name": "John Smith",
"last4": "4242",
"exp_month": "12",
"exp_year": "2025",
"fingerprint": "CC2XvyoohnqecEq4r3FtXv6MdCx4TbaW1UUTdCCN5MNL",
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z"
}

Verify Card for Adding to Profile​

When a customer adds a new payment method, use add_card verification type to validate it before saving:

Verify Card for Storage
curl 'https://api.publicsquare.com/payments' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: '09ec2c87-7fb8-44ca-bb18-5c71a76974da' \
-H 'Content-Type: application/json' \
-d '{
"amount": 0,
"currency": "USD",
"capture": false,
"verification": {
"type": "add_card"
},
"payment_method": {
"card": "card_AjkCFKAYiTsjghXWMzoXFPMxj"
},
"customer": {
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@email.com"
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
}
}'
The amount must be 0 and capture must be false for verification payments.

Verify Card for Recurring Payments​

When setting up a subscription or recurring billing, use recurring verification type:

Verify Card for Recurring
curl 'https://api.publicsquare.com/payments' \
-X 'POST' \
-H 'X-API-KEY: <SECRET_API_KEY>' \
-H 'IDEMPOTENCY-KEY: '19ec2c87-7fb8-44ca-bb18-5c71a76974db' \
-H 'Content-Type: application/json' \
-d '{
"amount": 0,
"currency": "USD",
"capture": false,
"verification": {
"type": "recurring"
},
"payment_method": {
"card": "card_AjkCFKAYiTsjghXWMzoXFPMxj"
},
"customer": {
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@email.com"
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
}
}'

Verification Types​

TypeDescriptionUse Case
add_cardVerify card for storageCustomer adds a new payment method
recurringVerify card for recurring billingSetting up subscriptions or recurring charges

Verification Response​

You should see a payment response with a succeeded status:

Verification Payment Response
{
"id": "pmt_2YKewBonG4tgk12MheY3PiHDy",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "test",
"status": "succeeded",
"transaction_id": "trx_95rvMJvAVeG68W4NtLdfkN3LG",
"amount": 0,
"amount_charged": 0,
"amount_capturable": 0,
"amount_refunded": 0,
"refunded": false,
"currency": "USD",
"verification": {
"type": "add_card",
"result": {
"card_security_code": "matched",
"address_line_1": "matched",
"postal_code": "matched",
"cardholder_name": "not_checked"
}
},
"payment_method": {
"card": {
"id": "card_AjkCFKAYiTsjghXWMzoXFPMxj",
"cardholder_name": "John Smith",
"last4": "4242",
"exp_month": "12",
"exp_year": "2025",
"brand": "visa",
"avs_code": "Y",
"cvv2_reply": "M",
"fingerprint": "CC2XvyoohnqecEq4r3FtXv6MdCx4TbaW1UUTdCCN5MNL"
}
},
"customer": {
"id": "cus_7Ay5mcUXAxwrN6wQEQUVEHBCJ",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@email.com"
},
"billing_details": {
"address_line_1": "111 Test St.",
"city": "Des Moines",
"state": "IA",
"postal_code": "51111",
"country": "US"
},
"fraud_decision": {
"decision": "accept"
},
"transaction": {
"id": "trx_95rvMJvAVeG68W4NtLdfkN3LG",
"account_id": "acc_B518niGwGYKzig6vtrRVZGGGV",
"environment": "test",
"status": "succeeded",
"amount": 0,
"fee_amount": 0,
"net_amount": 0,
"currency": "USD",
"type_id": "pmt_2YKewBonG4tgk12MheY3PiHDy",
"type": "payment",
"processor": "nuvei",
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z"
},
"created_at": "2024-06-30T01:02:29.212Z",
"modified_at": "2024-06-30T01:02:29.212Z"
}
Unlike standard authorizations that require capture, verification payments return a succeeded status immediately since there is no amount to capture.

Read the Verification Result​

A succeeded status means the verification ran. It does not mean every check passed. Read verification.result to decide whether to store the card.

verification.result reports each check the issuer performed:

FieldCheck
card_security_codeThe CVV or CVC on the card
address_line_1The street address
postal_codeThe postal code
cardholder_nameThe name on the card

Each field returns one of five values:

ValueMeaning
matchedThe issuer confirmed the value
not_matchedThe issuer says the value does not match
partially_matchedThe value partly matches. Name checks only
not_checkedThe issuer did not run this check
unavailableThe issuer could not answer, or you did not send the value

not_checked and unavailable are not failures. They mean the issuer returned no answer, so you cannot treat them as a pass or a fail.

The avs_code and cvv2_reply fields on the card carry the same information in raw network codes. Use verification.result for new integrations.

A Failed Check Still Succeeds​

This card returned a wrong postal code and a wrong security code. The payment status is still succeeded:

Failed Checks
{
"id": "pmt_3ZLfwCpnH5ukl23OifZ4QPNzk",
"status": "succeeded",
"amount": 0,
"payment_method": {
"card": {
"id": "card_AjkCFKAYiTsjghXWMzoXFPMxj",
"avs_code": "N",
"cvv2_reply": "N"
}
},
"verification": {
"type": "add_card",
"result": {
"card_security_code": "not_matched",
"address_line_1": "unavailable",
"postal_code": "not_matched",
"cardholder_name": "matched"
}
}
}

Verify With a Postal Code Only​

You can collect a postal code and no street address. Send billing_details with postal_code alone:

Postal Code Only
{
"amount": 0,
"capture": false,
"currency": "USD",
"payment_method": {
"card": "card_AjkCFKAYiTsjghXWMzoXFPMxj"
},
"verification": {
"type": "add_card"
},
"billing_details": {
"postal_code": "51111"
}
}

The issuer then has no street address to check, so address_line_1 returns unavailable. This is expected and is not a failure:

Postal Code Only Result
{
"payment_method": {
"card": {
"avs_code": "Z",
"cvv2_reply": "M"
}
},
"verification": {
"type": "add_card",
"result": {
"card_security_code": "matched",
"address_line_1": "unavailable",
"postal_code": "matched",
"cardholder_name": "matched"
}
}
}

avs_code is Z when the postal code matches and no street address was sent. It is N when the postal code does not match.

Validation Rules​

When creating verification payments, the following rules apply:

  • amount must be 0 when verification is provided
  • verification is required when amount is 0
  • capture must be false for verification payments
  • verification.type must be either add_card or recurring

Handling Declined Verifications​

A declined or rejected status means the issuer refused the authorization itself, for example a closed or blocked card. This is different from a check that returns not_matched:

Declined Verification Response
{
"id": "pmt_3ZLfwCpnH5ukl23OifZ4QPNzk",
"status": "declined",
"amount": 0,
"verification": {
"type": "add_card"
},
"decline_reason": "do_not_honor",
...
}

Tell the customer that you could not verify the card, and ask for another payment method.

Handle the two outcomes separately:

  • A declined status. The card is unusable. Ask for another card.
  • A succeeded status with a failed check in verification.result. The card works, but a detail does not match. Ask the customer to correct that detail, or apply your own risk rule.

Conclusion​

Zero-dollar authorizations provide a secure way to validate payment cards without processing an actual charge. This is particularly useful for:

  • Building trust with customers by verifying cards upfront
  • Reducing failed transactions in recurring billing scenarios
  • Improving the checkout experience for card-on-file workflows

Follow these guides to learn more: