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

This guide verifies a card with a zero-dollar authorization.

You need a saved card for this guide. Save one with Save Cards, from your web app or from your servers. Either way you get a card id that starts with card_.

Before you start​

Credova account
Sign up or sign in to the Credova Portal.
Secret Key
Authenticates requests from your server. Never send it to the browser.

Create a Verification Payment​

We will use a saved card to create a verification payment.

For example, given this saved 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"
}

Standard authorizations need a capture. Verification payments do not, because there is no amount to capture. They return a succeeded status immediately.

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: