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.
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:
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"
}
}'
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:
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
| Type | Description | Use Case |
|---|---|---|
add_card | Verify card for storage | Customer adds a new payment method |
recurring | Verify card for recurring billing | Setting up subscriptions or recurring charges |
Verification Response
You should see a payment response with a succeeded status:
{
"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"
}
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:
| Field | Check |
|---|---|
card_security_code | The CVV or CVC on the card |
address_line_1 | The street address |
postal_code | The postal code |
cardholder_name | The name on the card |
Each field returns one of five values:
| Value | Meaning |
|---|---|
matched | The issuer confirmed the value |
not_matched | The issuer says the value does not match |
partially_matched | The value partly matches. Name checks only |
not_checked | The issuer did not run this check |
unavailable | The 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:
{
"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:
{
"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:
{
"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:
amountmust be0whenverificationis providedverificationis required whenamountis0capturemust befalsefor verification paymentsverification.typemust be eitheradd_cardorrecurring
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:
{
"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
declinedstatus. The card is unusable. Ask for another card. - A
succeededstatus with a failed check inverification.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:
- Process Card Payments - Charge verified cards
- Authorize and Capture Payments - Pre-authorize payments
- Search and View Transactions - Monitor verification transactions