Financial · API reference

Cards

Read a payment card

POST/v2/cards/readcards.read

Reads every card in a photo: number, expiry and holder with their confidences, the checks (Luhn, length for the network, expiry), the BIN record and the issuer in the bank directory. The full number is in this response only; the stored copy keeps the first six and last four digits, and the photo is never stored.

Price: 0.03 credits per successful call.

Form fields (multipart)

imagefilerequired

The card photo: JPG, PNG or BMP, up to 10 MB. The photo is never stored.

Returns

The read ran; check status.

Show the CardResponse fields
idstringrequired

Scan id, crd_ followed by 12 characters.

objectstringrequired

Always card.

created_atstring (date-time)required

When it was created (ISO 8601, UTC).

sourcestringrequired

Where the call came from, as shown in the console's logs.

apisdkplayground
envstringrequired

The environment the read is recorded in: the credential's.

livetest
processing_msintegerrequired

How long the engine took, in milliseconds.

statusstringrequired

partial: read, but something a caller relies on is missing or failed a check (issue_code says what). unreadable: nothing to read.

readpartialunreadable
issue_codestring

Why a read is partial or unreadable: no_micr_line, routing_checksum_failed, routing_prefix_invalid, layout_unrecognised, weak_characters, no_card, number_unreadable, luhn_failed, low_confidence.

issuestring

Plain-words reason, when not read.

imageobjectrequired

Dimensions only: card photos are never stored.

Show 2 fields
widthintegerrequired
heightintegerrequired
cards_detectedintegerrequired
cardsarray of objectsrequired

Every card found, strongest first.

Show 21 fields
indexintegerrequired
descriptionstring

The engine's label, for example Card #1.

fieldsarray of objects

Every field the engine read, verbatim.

Show 3 fields
namestringrequired

Field name: number, valid_thru, holder_name…

valuestring
confidencenumber

0 to 100.

confidencenumberrequired

Summary confidence for the card, 0 to 100.

warpedBoxarray of numbers

The engine's own box, verbatim.

boxarray of numbersrequired

Four corners x1,y1 … x4,y4, in image pixels.

numberstring

The full number: in the read response only, never in stored copies.

first6string
last4string
lengthintegerrequired

Digits in the number; 0 when it could not be read.

fingerprintstring

Keyed hash of the number, cf_ + 24 hex: stable across scans, safe to store.

luhn_validbooleanrequired
scheme_validbooleanrequired

Luhn and a length that fits the network.

scheme_checksobjectrequired
Show 3 fields
luhnbooleanrequired
lengthbooleanrequired
iin_knownbooleanrequired

The BIN is in the tables.

network_from_prefixstring
expiredboolean
expires_in_daysinteger

Negative once expired.

expiry_statusstringrequired

expiring_soon: 60 days or less left.

validexpiring_soonexpiredunknown
binobject

Who issued a card. Fields that are unknown are absent.

Show 22 fields
binstringrequired

The first 6 to 8 digits.

networkstring

Visa, Mastercard, American Express, Discover…

typestring

Debit, Credit…

levelstring

Classic, Gold, World…

issuerstring

The issuing bank's name.

countrystring

Issuing country, ISO 3166-1 alpha-2.

country_namestring
country_code3string
flagstring

Flag emoji.

flag_urlstring

The country's flag (SVG), relative to the API base.

bankobject or any

The issuer in the bank directory, with logo. Returned by GET /v2/bin/{digits}.

currencystring

ISO 4217.

currency_namestring
fundingstring
creditdebitprepaidchargeunknown
is_prepaidboolean
is_commercialboolean
is_reloadableboolean
categorystring
consumercommercial
issuer_countrystring
phonestring

Issuer contact, when known.

urlstring

Issuer website, when known.

sourcestring

Which tier answered.

bankobject or any
number_validboolean

The engine's own card-level pass flag.

cardobject

One payment card in a photo.

Show 21 fields
indexintegerrequired
descriptionstring

The engine's label, for example Card #1.

fieldsarray of objects

Every field the engine read, verbatim.

Show 3 fields
namestringrequired

Field name: number, valid_thru, holder_name…

valuestring
confidencenumber

0 to 100.

confidencenumberrequired

Summary confidence for the card, 0 to 100.

warpedBoxarray of numbers

The engine's own box, verbatim.

boxarray of numbersrequired

Four corners x1,y1 … x4,y4, in image pixels.

numberstring

The full number: in the read response only, never in stored copies.

first6string
last4string
lengthintegerrequired

Digits in the number; 0 when it could not be read.

fingerprintstring

Keyed hash of the number, cf_ + 24 hex: stable across scans, safe to store.

luhn_validbooleanrequired
scheme_validbooleanrequired

Luhn and a length that fits the network.

scheme_checksobjectrequired
Show 3 fields
luhnbooleanrequired
lengthbooleanrequired
iin_knownbooleanrequired

The BIN is in the tables.

network_from_prefixstring
expiredboolean
expires_in_daysinteger

Negative once expired.

expiry_statusstringrequired

expiring_soon: 60 days or less left.

validexpiring_soonexpiredunknown
binobject

Who issued a card. Fields that are unknown are absent.

Show 22 fields
binstringrequired

The first 6 to 8 digits.

networkstring

Visa, Mastercard, American Express, Discover…

typestring

Debit, Credit…

levelstring

Classic, Gold, World…

issuerstring

The issuing bank's name.

countrystring

Issuing country, ISO 3166-1 alpha-2.

country_namestring
country_code3string
flagstring

Flag emoji.

flag_urlstring

The country's flag (SVG), relative to the API base.

bankobject or any

The issuer in the bank directory, with logo. Returned by GET /v2/bin/{digits}.

currencystring

ISO 4217.

currency_namestring
fundingstring
creditdebitprepaidchargeunknown
is_prepaidboolean
is_commercialboolean
is_reloadableboolean
categorystring
consumercommercial
issuer_countrystring
phonestring

Issuer contact, when known.

urlstring

Issuer website, when known.

sourcestring

Which tier answered.

bankobject or any
number_validboolean

The engine's own card-level pass flag.

binobject

Who issued a card. Fields that are unknown are absent.

Show 22 fields
binstringrequired

The first 6 to 8 digits.

networkstring

Visa, Mastercard, American Express, Discover…

typestring

Debit, Credit…

levelstring

Classic, Gold, World…

issuerstring

The issuing bank's name.

countrystring

Issuing country, ISO 3166-1 alpha-2.

country_namestring
country_code3string
flagstring

Flag emoji.

flag_urlstring

The country's flag (SVG), relative to the API base.

bankobject or any

The issuer in the bank directory, with logo. Returned by GET /v2/bin/{digits}.

currencystring

ISO 4217.

currency_namestring
fundingstring
creditdebitprepaidchargeunknown
is_prepaidboolean
is_commercialboolean
is_reloadableboolean
categorystring
consumercommercial
issuer_countrystring
phonestring

Issuer contact, when known.

urlstring

Issuer website, when known.

sourcestring

Which tier answered.

bankobject or any

Errors

  • 400A field is missing or not valid.
  • 401No API key, or the key is not valid, expired or revoked.
  • 402Not enough credits for this call (insufficient_credits), or the key reached its spend cap. Nothing was charged.
  • 403The key may not call this API (permission, environment or IP allow-list). Nothing was charged.
  • 413The image or the request is too large.
  • 415The file type is not accepted (JPG, PNG or BMP).
  • 429Too many requests for this key: wait Retry-After seconds. Nothing was charged.
  • 5XXThe check could not run. Nothing was charged.
Request
curl -X POST https://verisec.dev/v2/cards/read \
  -H "Authorization: Bearer $VERISEC_API_KEY" \
  -F image=@card-visa.jpg
Response · 200
{
  "id": "crd_QVvX1lY05q56",
  "object": "card",
  "created_at": "2026-10-16T08:46:10.000Z",
  "source": "api",
  "env": "test",
  "processing_ms": 1046,
  "image": {
    "width": 900,
    "height": 1200
  },
  "status": "read",
  "cards_detected": 1,
  "cards": [
    {
      "index": 0,
      "confidence": 99.61734,
      "description": "Card #1",
      "fields": [
        {
          "confidence": 92.40817,
          "name": "number",
          "valid": true,
          "value": "4242424242424242",
          "box": [
            125,
            621,
            690,
            621,
            690,
            669,
            125,
            669
          ]
        },
        {
          "confidence": 89.78328,
          "name": "valid_thru",
          "value": "09/29",
          "box": [
            419,
            696,
            515,
            696,
            515,
            726,
            419,
            726
          ]
        },
        {
          "confidence": 84.54898,
          "name": "holder_name",
          "value": "KEZA AMANI",
          "box": [
            125,
            758,
            329,
            758,
            329,
            788,
            125,
            788
          ]
        }
      ],
      "number_valid": true,
      "warpedBox": [
        70.1301,
        360.1412,
        830.0774,
        359.9733,
        830.102,
        838.9948,
        69.9964,
        838.7739
      ],
      "box": [
        70,
        360,
        830,
        360,
        830,
        839,
        70,
        839
      ],
      "number": "4242424242424242",
      "first6": "424242",
      "last4": "4242",
      "length": 16,
      "fingerprint": "cf_f7423c941cbe11f80a824f3e",
      "luhn_valid": true,
      "scheme_valid": true,
      "scheme_checks": {
        "luhn": true,
        "length": true,
        "iin_known": true
      },
      "network_from_prefix": "Visa",
      "expired": false,
      "expires_in_days": 1080,
      "expiry_status": "valid",
      "bin": {
        "network": "Visa",
        "type": "Debit",
        "level": "Classic",
        "funding": "debit",
        "issuer": "Aeron Fintech",
        "country": "RW",
        "currency": "RWF",
        "is_commercial": false,
        "is_prepaid": false,
        "url": "https://aeron-fintech.example",
        "source": "local+online",
        "bin": "424242",
        "category": "consumer",
        "is_reloadable": true,
        "country_name": "Rwanda",
        "country_code3": "RWA",
        "issuer_country": "RW",
        "flag": "🇷🇼",
        "currency_name": "Rwanda Franc",
        "flag_url": "/v2/flags/rw.svg"
      },
      "bank": {
        "read": {
          "name": "Aeron Fintech",
          "country": "RW"
        },
        "resolved": {
          "profile_id": "bank_1d4e94dde9d17fc07f",
          "name": "Aeron Fintech",
          "country": "Rwanda",
          "country_code": "RW",
          "city": "Kigali",
          "address": "Aeron House, 14 Innovation Way, Kigali",
          "status": "active",
          "logo_url": "/v2/banks/bank_1d4e94dde9d17fc07f/logo",
          "flag_url": "/v2/flags/rw.svg"
        },
        "match_confidence": 1,
        "name_match": 0.99,
        "alternatives": []
      }
    }
  ],
  "card": {
    "index": 0,
    "confidence": 99.61734,
    "description": "Card #1",
    "fields": [
      {
        "confidence": 92.40817,
        "name": "number",
        "valid": true,
        "value": "4242424242424242",
        "box": [
          125,
          621,
          690,
          621,
          690,
          669,
          125,
          669
        ]
      },
      {
        "confidence": 89.78328,
        "name": "valid_thru",
        "value": "09/29",
        "box": [
          419,
          696,
          515,
          696,
          515,
          726,
          419,
          726
        ]
      },
      {
        "confidence": 84.54898,
        "name": "holder_name",
        "value": "KEZA AMANI",
        "box": [
          125,
          758,
          329,
          758,
          329,
          788,
          125,
          788
        ]
      }
    ],
    "number_valid": true,
    "warpedBox": [
      70.1301,
      360.1412,
      830.0774,
      359.9733,
      830.102,
      838.9948,
      69.9964,
      838.7739
    ],
    "box": [
      70,
      360,
      830,
      360,
      830,
      839,
      70,
      839
    ],
    "number": "4242424242424242",
    "first6": "424242",
    "last4": "4242",
    "length": 16,
    "fingerprint": "cf_f7423c941cbe11f80a824f3e",
    "luhn_valid": true,
    "scheme_valid": true,
    "scheme_checks": {
      "luhn": true,
      "length": true,
      "iin_known": true
    },
    "network_from_prefix": "Visa",
    "expired": false,
    "expires_in_days": 1080,
    "expiry_status": "valid"
  },
  "bin": {
    "network": "Visa",
    "type": "Debit",
    "level": "Classic",
    "funding": "debit",
    "issuer": "Aeron Fintech",
    "country": "RW",
    "currency": "RWF",
    "is_commercial": false,
    "is_prepaid": false,
    "url": "https://aeron-fintech.example",
    "source": "local+online",
    "bin": "424242",
    "category": "consumer",
    "is_reloadable": true,
    "country_name": "Rwanda",
    "country_code3": "RWA",
    "issuer_country": "RW",
    "flag": "🇷🇼",
    "currency_name": "Rwanda Franc",
    "flag_url": "/v2/flags/rw.svg"
  },
  "bank": {
    "read": {
      "name": "Aeron Fintech",
      "country": "RW"
    },
    "resolved": {
      "profile_id": "bank_1d4e94dde9d17fc07f",
      "name": "Aeron Fintech",
      "country": "Rwanda",
      "country_code": "RW",
      "city": "Kigali",
      "address": "Aeron House, 14 Innovation Way, Kigali",
      "status": "active",
      "logo_url": "/v2/banks/bank_1d4e94dde9d17fc07f/logo",
      "flag_url": "/v2/flags/rw.svg"
    },
    "match_confidence": 1,
    "name_match": 0.99,
    "alternatives": []
  }
}

Read a card number

POST/v2/cards/numbercards.number

Reads the card number from a photo, with its network and checks. Nothing is stored.

Price: 0.02 credits per successful call.

Form fields (multipart)

imagefilerequired

The card photo: JPG, PNG or BMP, up to 10 MB. The photo is never stored.

Returns

The read ran; check status.

Show the CardNumber fields
objectstringrequired

Always card_number.

statusstringrequired

partial: read, but something a caller relies on is missing or failed a check (issue_code says what). unreadable: nothing to read.

readpartialunreadable
issue_codestring

Why a read is partial or unreadable: no_micr_line, routing_checksum_failed, routing_prefix_invalid, layout_unrecognised, weak_characters, no_card, number_unreadable, luhn_failed, low_confidence.

issuestring
processing_msintegerrequired

How long the engine took, in milliseconds.

numberstring

The full number: in this response only, never stored.

first6string
last4string
lengthinteger
networkstring
luhn_validboolean
scheme_validboolean
confidencenumber

0 to 100.

Errors

  • 400A field is missing or not valid.
  • 401No API key, or the key is not valid, expired or revoked.
  • 402Not enough credits for this call (insufficient_credits), or the key reached its spend cap. Nothing was charged.
  • 403The key may not call this API (permission, environment or IP allow-list). Nothing was charged.
  • 413The image or the request is too large.
  • 415The file type is not accepted (JPG, PNG or BMP).
  • 429Too many requests for this key: wait Retry-After seconds. Nothing was charged.
  • 5XXThe check could not run. Nothing was charged.
Request
curl -X POST https://verisec.dev/v2/cards/number \
  -H "Authorization: Bearer $VERISEC_API_KEY" \
  -F image=@card-visa.jpg
Response · 200
{
  "object": "card_number",
  "status": "read",
  "processing_ms": 920,
  "number": "4242424242424242",
  "first6": "424242",
  "last4": "4242",
  "length": 16,
  "network": "Visa",
  "luhn_valid": true,
  "scheme_valid": true,
  "confidence": 92.4
}

Read a card's expiry date

POST/v2/cards/expirycards.expiry

Reads the expiry date from a card photo and works out whether the card has expired and how many days it has left. Nothing is stored.

Price: 0.02 credits per successful call.

Form fields (multipart)

imagefilerequired

The card photo: JPG, PNG or BMP, up to 10 MB. The photo is never stored.

Returns

The read ran; check status.

Show the CardExpiry fields
objectstringrequired

Always card_expiry.

statusstringrequired

partial: read, but something a caller relies on is missing or failed a check (issue_code says what). unreadable: nothing to read.

readpartialunreadable
issue_codestring

Why a read is partial or unreadable: no_micr_line, routing_checksum_failed, routing_prefix_invalid, layout_unrecognised, weak_characters, no_card, number_unreadable, luhn_failed, low_confidence.

issuestring
valid_thrustring

MM/YY as printed.

valid_fromstring

MM/YY, when printed.

expiredboolean
expires_in_daysinteger

Negative once expired.

expiry_statusstring

expiring_soon: 60 days or less left.

validexpiring_soonexpiredunknown
confidencenumber

0 to 100.

processing_msintegerrequired

How long the engine took, in milliseconds.

Errors

  • 400A field is missing or not valid.
  • 401No API key, or the key is not valid, expired or revoked.
  • 402Not enough credits for this call (insufficient_credits), or the key reached its spend cap. Nothing was charged.
  • 403The key may not call this API (permission, environment or IP allow-list). Nothing was charged.
  • 413The image or the request is too large.
  • 415The file type is not accepted (JPG, PNG or BMP).
  • 429Too many requests for this key: wait Retry-After seconds. Nothing was charged.
  • 5XXThe check could not run. Nothing was charged.
Request
curl -X POST https://verisec.dev/v2/cards/expiry \
  -H "Authorization: Bearer $VERISEC_API_KEY" \
  -F image=@card-visa.jpg
Response · 200
{
  "object": "card_expiry",
  "status": "read",
  "valid_thru": "09/29",
  "expired": false,
  "expires_in_days": 1080,
  "expiry_status": "valid",
  "confidence": 89.5,
  "processing_ms": 1251
}

Check a card number

POST/v2/cards/checkcards.check

Checks a typed card number, for example from a checkout form: the Luhn checksum, a length that fits the network, the expiry when sent, and the BIN record. Accept the card when scheme_valid is true and expired is not. Only the first six and last four digits come back; nothing is stored.

Price: 0.002 credits per successful call.

Body parameters

numberstringrequired

12 to 19 digits; spaces are ignored. Never stored.

expirystring

MM/YY.

Returns

The checks ran.

Show the CardCheck fields
objectstringrequired

Always card_check.

first6stringrequired
last4stringrequired
lengthintegerrequired
networkstring
luhn_validbooleanrequired
length_validbooleanrequired

The length fits the network.

scheme_validbooleanrequired

Luhn and length both hold.

expiredboolean

When an expiry was sent.

expires_in_daysinteger

When an expiry was sent.

expiry_statusstring

expiring_soon: 60 days or less left.

validexpiring_soonexpiredunknown
binobject

Who issued a card. Fields that are unknown are absent.

Show 22 fields
binstringrequired

The first 6 to 8 digits.

networkstring

Visa, Mastercard, American Express, Discover…

typestring

Debit, Credit…

levelstring

Classic, Gold, World…

issuerstring

The issuing bank's name.

countrystring

Issuing country, ISO 3166-1 alpha-2.

country_namestring
country_code3string
flagstring

Flag emoji.

flag_urlstring

The country's flag (SVG), relative to the API base.

bankobject or any

The issuer in the bank directory, with logo. Returned by GET /v2/bin/{digits}.

currencystring

ISO 4217.

currency_namestring
fundingstring
creditdebitprepaidchargeunknown
is_prepaidboolean
is_commercialboolean
is_reloadableboolean
categorystring
consumercommercial
issuer_countrystring
phonestring

Issuer contact, when known.

urlstring

Issuer website, when known.

sourcestring

Which tier answered.

Errors

  • 400A field is missing or not valid.
  • 401No API key, or the key is not valid, expired or revoked.
  • 402Not enough credits for this call (insufficient_credits), or the key reached its spend cap. Nothing was charged.
  • 403The key may not call this API (permission, environment or IP allow-list). Nothing was charged.
  • 429Too many requests for this key: wait Retry-After seconds. Nothing was charged.
  • 5XXThe check could not run. Nothing was charged.
Request
curl -X POST https://verisec.dev/v2/cards/check \
  -H "Authorization: Bearer $VERISEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "4242 4242 4242 4242",
    "expiry": "09/29"
  }'
Response · 200
{
  "object": "card_check",
  "first6": "424242",
  "last4": "4242",
  "length": 16,
  "network": "Visa",
  "luhn_valid": true,
  "length_valid": true,
  "scheme_valid": true,
  "expired": false,
  "expires_in_days": 1080,
  "expiry_status": "valid",
  "bin": {
    "network": "Visa",
    "type": "Debit",
    "level": "Classic",
    "funding": "debit",
    "issuer": "Aeron Fintech",
    "country": "RW",
    "currency": "RWF",
    "is_commercial": false,
    "is_prepaid": false,
    "url": "https://aeron-fintech.example",
    "source": "local+online",
    "bin": "424242",
    "category": "consumer",
    "is_reloadable": true,
    "country_name": "Rwanda",
    "country_code3": "RWA",
    "issuer_country": "RW",
    "flag": "🇷🇼",
    "currency_name": "Rwanda Franc",
    "flag_url": "/v2/flags/rw.svg"
  }
}

Fingerprint a card number

POST/v2/cards/fingerprintcards.fingerprint

Turns a card number into a fingerprint: always the same for the same card, and impossible to turn back into the number. Store it to recognise a card you have seen before; a card read from a photo carries the same fingerprint.

Price: 0.002 credits per successful call.

Body parameters

numberstringrequired

12 to 19 digits; spaces are ignored. Never stored.

Returns

The fingerprint.

Show the CardFingerprint fields
objectstringrequired

Always card_fingerprint.

fingerprintstringrequired

cf_ + 24 hex. The same card always gives the same value; it cannot be turned back into the number.

first6stringrequired
last4stringrequired

Errors

  • 400A field is missing or not valid.
  • 401No API key, or the key is not valid, expired or revoked.
  • 402Not enough credits for this call (insufficient_credits), or the key reached its spend cap. Nothing was charged.
  • 403The key may not call this API (permission, environment or IP allow-list). Nothing was charged.
  • 429Too many requests for this key: wait Retry-After seconds. Nothing was charged.
  • 5XXThe check could not run. Nothing was charged.
Request
curl -X POST https://verisec.dev/v2/cards/fingerprint \
  -H "Authorization: Bearer $VERISEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "4242 4242 4242 4242"
  }'
Response · 200
{
  "object": "card_fingerprint",
  "fingerprint": "cf_f7423c941cbe11f80a824f3e",
  "first6": "424242",
  "last4": "4242"
}