Procare Pay Integration Service

Complete API Documentation for Payment Processing

Get BIN Information (Single BIN)

GET /v1/rest/bins/{binId}

Description: Retrieves Bank Identification Number (BIN) information for a single credit card based on the BIN ID or the first 6-8 digits of the card number.

What is this endpoint used for?

This endpoint helps you identify details about a credit card before processing a transaction. Think of it like looking up a phone number to find out which carrier it belongs to:

  • Card Brand Detection: Identify if it's a Visa, Mastercard, Amex, or Discover card
  • Card Type: Determine if it's a credit, debit, or prepaid card
  • Surcharge Eligibility: Check if surcharges are allowed for this card type
  • Bank Information: Find out which bank issued the card
  • User Experience: Display the correct card logo or customize payment flow
  • Fraud Prevention: Validate that the card type matches what the customer claims

What is a BIN?

A Bank Identification Number (BIN) is the first 6-8 digits of a credit or debit card number. It identifies:

  • The card brand (Visa, Mastercard, etc.)
  • The issuing bank or financial institution
  • The card type (credit, debit, prepaid)
  • The card's country of origin
Example: For card number 4111 1111 1111 1111, the BIN is 411111 or 41111111 (first 6 or 8 digits). This BIN identifies it as a Visa card.

Path Parameters

binId (required)
Type: string
Description: The BIN ID (a unique identifier) OR the first 6-8 digits of a credit card number
Examples:
  • 411111 - First 6 digits of a Visa card
  • 41111111 - First 8 digits of a Visa card
  • 540123 - First 6 digits of a Mastercard

Authentication

This endpoint requires bearer token authentication using the Authorization header.

Note: The bearer token must be a valid Cognito token obtained through the OAuth2 authentication flow.

Code Examples

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

public class IssuerInformation
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("country")]
    public string Country { get; set; }

    [JsonProperty("phoneNumber")]
    public string PhoneNumber { get; set; }
}

public class BinResponse
{
    [JsonProperty("binId")]
    public string BinId { get; set; }

    [JsonProperty("cardType")]
    public string CardType { get; set; }

    [JsonProperty("brandName")]
    public string BrandName { get; set; }

    [JsonProperty("fundingSource")]
    public string FundingSource { get; set; }

    [JsonProperty("bin")]
    public string Bin { get; set; }

    [JsonProperty("issuerInformation")]
    public IssuerInformation IssuerInformation { get; set; }

    [JsonProperty("surcharge")]
    public string Surcharge { get; set; }
}

public class BinClient
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl = "https://your-api-domain.com";

    public BinClient()
    {
        _httpClient = new HttpClient();
        _httpClient.BaseAddress = new Uri(_baseUrl);
    }

    public async Task<BinResponse> GetBinInfoAsync(string binId)
    {
        try
        {
            // Validate input
            if (string.IsNullOrEmpty(binId) || binId.Length < 6)
            {
                throw new ArgumentException("BIN ID must be at least 6 digits", nameof(binId));
            }

            // Construct the endpoint URL
            string endpoint = $"/v1/rest/bins/{binId}";

            // Make the GET request
            HttpResponseMessage response = await _httpClient.GetAsync(endpoint);

            // Ensure the request was successful
            response.EnsureSuccessStatusCode();

            // Read and deserialize the response
            string responseBody = await response.Content.ReadAsStringAsync();
            BinResponse binInfo = JsonConvert.DeserializeObject<BinResponse>(responseBody);

            return binInfo;
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Request error: {e.Message}");
            throw;
        }
    }

    // Helper method: Extract BIN from full card number
    public string ExtractBin(string cardNumber, int binLength = 8)
    {
        // Remove spaces and non-numeric characters
        string cleaned = new string(cardNumber.Where(char.IsDigit).ToArray());

        // Return first 6-8 digits
        return cleaned.Substring(0, Math.Min(binLength, cleaned.Length));
    }
}

// Example usage:
var client = new BinClient();

// Look up BIN using first 8 digits of card
string cardNumber = "4111111111111111";
string bin = client.ExtractBin(cardNumber, 8);

BinResponse binInfo = await client.GetBinInfoAsync(bin);

Console.WriteLine($"Card Brand: {binInfo.BrandName}");
Console.WriteLine($"Card Type: {binInfo.CardType}");
Console.WriteLine($"Issuing Bank: {binInfo.IssuerInformation?.Name}");
Console.WriteLine($"Surcharge Allowed: {binInfo.Surcharge}");
Imports System.Net.Http
Imports System.Threading.Tasks
Imports Newtonsoft.Json

Public Class IssuerInformation
    <JsonProperty("name")>
    Public Property Name As String

    <JsonProperty("country")>
    Public Property Country As String

    <JsonProperty("phoneNumber")>
    Public Property PhoneNumber As String
End Class

Public Class BinResponse
    <JsonProperty("binId")>
    Public Property BinId As String

    <JsonProperty("cardType")>
    Public Property CardType As String

    <JsonProperty("brandName")>
    Public Property BrandName As String

    <JsonProperty("fundingSource")>
    Public Property FundingSource As String

    <JsonProperty("bin")>
    Public Property Bin As String

    <JsonProperty("issuerInformation")>
    Public Property IssuerInformation As IssuerInformation

    <JsonProperty("surcharge")>
    Public Property Surcharge As String
End Class

Public Class BinClient
    Private ReadOnly _httpClient As HttpClient
    Private ReadOnly _baseUrl As String = "https://your-api-domain.com"

    Public Sub New()
        _httpClient = New HttpClient()
        _httpClient.BaseAddress = New Uri(_baseUrl)
    End Sub

    Public Async Function GetBinInfoAsync(binId As String) As Task(Of BinResponse)
        Try
            ' Validate input
            If String.IsNullOrEmpty(binId) OrElse binId.Length < 6 Then
                Throw New ArgumentException("BIN ID must be at least 6 digits", NameOf(binId))
            End If

            ' Construct the endpoint URL
            Dim endpoint As String = $"/v1/rest/bins/{binId}"

            ' Make the GET request
            Dim response As HttpResponseMessage = Await _httpClient.GetAsync(endpoint)

            ' Ensure the request was successful
            response.EnsureSuccessStatusCode()

            ' Read and deserialize the response
            Dim responseBody As String = Await response.Content.ReadAsStringAsync()
            Dim binInfo As BinResponse = JsonConvert.DeserializeObject(Of BinResponse)(responseBody)

            Return binInfo
        Catch ex As HttpRequestException
            Console.WriteLine($"Request error: {ex.Message}")
            Throw
        End Try
    End Function

    ' Helper method: Extract BIN from full card number
    Public Function ExtractBin(cardNumber As String, Optional binLength As Integer = 8) As String
        ' Remove spaces and non-numeric characters
        Dim cleaned As String = New String(cardNumber.Where(AddressOf Char.IsDigit).ToArray())

        ' Return first 6-8 digits
        Return cleaned.Substring(0, Math.Min(binLength, cleaned.Length))
    End Function
End Class

' Example usage:
Dim client As New BinClient()

' Look up BIN using first 8 digits of card
Dim cardNumber As String = "4111111111111111"
Dim bin As String = client.ExtractBin(cardNumber, 8)

Dim binInfo As BinResponse = Await client.GetBinInfoAsync(bin)

Console.WriteLine($"Card Brand: {binInfo.BrandName}")
Console.WriteLine($"Card Type: {binInfo.CardType}")
Console.WriteLine($"Issuing Bank: {binInfo.IssuerInformation?.Name}")
Console.WriteLine($"Surcharge Allowed: {binInfo.Surcharge}")
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;

class IssuerInformation {
    @SerializedName("name")
    private String name;

    @SerializedName("country")
    private String country;

    @SerializedName("phoneNumber")
    private String phoneNumber;

    // Getters
    public String getName() { return name; }
    public String getCountry() { return country; }
    public String getPhoneNumber() { return phoneNumber; }
}

class BinResponse {
    @SerializedName("binId")
    private String binId;

    @SerializedName("cardType")
    private String cardType;

    @SerializedName("brandName")
    private String brandName;

    @SerializedName("fundingSource")
    private String fundingSource;

    @SerializedName("bin")
    private String bin;

    @SerializedName("issuerInformation")
    private IssuerInformation issuerInformation;

    @SerializedName("surcharge")
    private String surcharge;

    // Getters
    public String getBinId() { return binId; }
    public String getCardType() { return cardType; }
    public String getBrandName() { return brandName; }
    public String getFundingSource() { return fundingSource; }
    public String getBin() { return bin; }
    public IssuerInformation getIssuerInformation() { return issuerInformation; }
    public String getSurcharge() { return surcharge; }
}

public class BinClient {
    private final HttpClient httpClient;
    private final String baseUrl;
    private final Gson gson;

    public BinClient() {
        this.baseUrl = "https://your-api-domain.com";
        this.httpClient = HttpClient.newHttpClient();
        this.gson = new Gson();
    }

    public BinResponse getBinInfo(String binId) throws Exception {
        // Validate input
        if (binId == null || binId.length() < 6) {
            throw new IllegalArgumentException("BIN ID must be at least 6 digits");
        }

        // Construct the endpoint URL
        String endpoint = baseUrl + "/v1/rest/bins/" + binId;

        // Build the HTTP request
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(endpoint))
            .header("Accept", "application/json")
            .GET()
            .build();

        // Send the request and get response
        HttpResponse<String> response = httpClient.send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );

        // Check response status
        if (response.statusCode() == 200) {
            return gson.fromJson(response.body(), BinResponse.class);
        } else if (response.statusCode() == 404) {
            throw new Exception("BIN not found: " + binId);
        } else {
            throw new Exception("Request failed with status: " + response.statusCode());
        }
    }

    // Helper method: Extract BIN from full card number
    public String extractBin(String cardNumber, int binLength) {
        // Remove spaces and non-numeric characters
        String cleaned = cardNumber.replaceAll("[^0-9]", "");

        // Return first 6-8 digits
        return cleaned.substring(0, Math.min(binLength, cleaned.length()));
    }

    // Example usage
    public static void main(String[] args) {
        try {
            BinClient client = new BinClient();

            // Look up BIN using first 8 digits of card
            String cardNumber = "4111111111111111";
            String bin = client.extractBin(cardNumber, 8);

            BinResponse binInfo = client.getBinInfo(bin);

            System.out.println("Card Brand: " + binInfo.getBrandName());
            System.out.println("Card Type: " + binInfo.getCardType());
            System.out.println("Issuing Bank: " +
                (binInfo.getIssuerInformation() != null ?
                 binInfo.getIssuerInformation().getName() : "N/A"));
            System.out.println("Surcharge Allowed: " + binInfo.getSurcharge());
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
require 'net/http'
require 'uri'
require 'json'

class BinClient
  def initialize(base_url = 'https://your-api-domain.com')
    @base_url = base_url
  end

  def get_bin_info(bin_id)
    # Validate input
    raise ArgumentError, 'BIN ID must be at least 6 digits' if bin_id.nil? || bin_id.length < 6

    # Construct the endpoint URL
    uri = URI("#{@base_url}/v1/rest/bins/#{bin_id}")

    # Create HTTP request
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true if uri.scheme == 'https'
    http.read_timeout = 30

    request = Net::HTTP::Get.new(uri.path)
    request['Accept'] = 'application/json'

    # Send request and handle response
    response = http.request(request)

    case response.code.to_i
    when 200
      JSON.parse(response.body)
    when 404
      raise "BIN not found: #{bin_id}"
    else
      raise "Request failed with status: #{response.code} - #{response.message}"
    end
  rescue StandardError => e
    puts "Request error: #{e.message}"
    raise
  end

  # Helper method: Extract BIN from full card number
  def extract_bin(card_number, bin_length = 8)
    # Remove spaces and non-numeric characters
    cleaned = card_number.gsub(/[^0-9]/, '')

    # Return first 6-8 digits
    cleaned[0, [bin_length, cleaned.length].min]
  end
end

# Example usage:
client = BinClient.new

# Look up BIN using first 8 digits of card
card_number = '4111111111111111'
bin = client.extract_bin(card_number, 8)

bin_info = client.get_bin_info(bin)

puts "Card Brand: #{bin_info['brandName']}"
puts "Card Type: #{bin_info['cardType']}"
puts "Issuing Bank: #{bin_info.dig('issuerInformation', 'name') || 'N/A'}"
puts "Surcharge Allowed: #{bin_info['surcharge']}"

puts "\nFull Response:"
puts JSON.pretty_generate(bin_info)

Response Fields

Field Type Description
binId string The URL Base64 encoded BIN ID (128 bit GUID value) - internal identifier
cardType string The card type: Unknown, Credit, Debit, Prepaid, or Charge
brandName string The card brand name (e.g., "Visa", "Mastercard", "American Express", "Discover")
fundingSource string The funding source: Unknown, Credit, Debit, Prepaid, or Charge
bin string The actual BIN number (first 6-8 digits of the card)
issuerInformation object Information about the bank or institution that issued the card (see below)
surcharge string Surcharge eligibility: Unknown, Allowed, or NotAllowed

Issuer Information Fields

Field Type Description
name string The name of the issuing bank or financial institution
country string The ISO3166 Alpha2 country code (e.g., "US", "CA", "GB")
phoneNumber string The customer service phone number for the issuing bank

Example Response

{
  "binId": "YWJjMTIzNDU2Nzg5MGRlZg==",
  "cardType": "Credit",
  "brandName": "Visa",
  "fundingSource": "Credit",
  "bin": "41111111",
  "issuerInformation": {
    "name": "Chase Bank USA, N.A.",
    "country": "US",
    "phoneNumber": "1-800-555-0100"
  },
  "surcharge": "NotAllowed"
}

HTTP Status Codes

Status Code Description
200 Success - BIN information retrieved successfully
400 Bad Request - Invalid BIN ID parameter (e.g., too short or malformed)
404 Not Found - BIN not found in database
500 Internal Server Error - Server encountered an unexpected error

Understanding Card Types and Funding Sources

Card Type vs. Funding Source

These fields often have the same value but serve different purposes:

  • cardType: How the card product is marketed/branded by the issuer
  • fundingSource: How transactions are actually funded (technical classification)
Value Description Example
Credit Borrowing from the issuer; paid back monthly Visa Signature, Mastercard World Elite
Debit Direct withdrawal from checking/savings account Bank debit card with Visa/Mastercard logo
Prepaid Pre-loaded with funds; no credit line or bank account Gift cards, reloadable prepaid cards
Charge Must be paid in full each month (no revolving balance) Traditional American Express cards
Unknown BIN data not available or card type cannot be determined New BINs, international cards

Understanding Surcharge Rules

What is Surcharging?

Surcharging is the practice of adding an extra fee to credit card transactions to offset processing costs.

Surcharge Value Meaning Action
Allowed Surcharges are permitted for this card type You may add a surcharge fee (typically 2-4%)
NotAllowed Surcharges are prohibited for this card type Do NOT add surcharge fees; may result in penalties
Unknown Surcharge eligibility cannot be determined Treat as NotAllowed to be safe
Important Surcharge Rules:
  • Debit cards: Surcharging is typically NOT allowed
  • Credit cards: May be surcharged in most states (check local laws)
  • Prepaid cards: Usually NOT allowed to be surcharged
  • Maximum surcharge: Usually capped at your actual cost (often 2-4%)

Common Use Cases

1. Display Correct Card Logo

// User types first 6-8 digits of card
string partialCard = "411111";
BinResponse binInfo = await client.GetBinInfoAsync(partialCard);

// Show appropriate logo
if (binInfo.BrandName == "Visa")
{
    DisplayVisaLogo();
}
else if (binInfo.BrandName == "Mastercard")
{
    DisplayMastercardLogo();
}
// ... etc

2. Validate Card Type Matches User Selection

// User claims they're paying with a debit card
string cardNumber = GetCardNumberFromForm();
string bin = ExtractBin(cardNumber, 8);
BinResponse binInfo = await client.GetBinInfoAsync(bin);

if (userSelectedDebit && binInfo.CardType != "Debit")
{
    ShowWarning("This appears to be a " + binInfo.CardType + " card, not a debit card.");
}

3. Apply or Skip Surcharge Fee

decimal transactionAmount = 100.00m;
decimal surchargeAmount = 0m;

BinResponse binInfo = await client.GetBinInfoAsync(bin);

if (binInfo.Surcharge == "Allowed" && binInfo.CardType == "Credit")
{
    surchargeAmount = transactionAmount * 0.03m; // 3% surcharge
    Console.WriteLine($"Surcharge: ${surchargeAmount:F2}");
}
else
{
    Console.WriteLine("No surcharge for this card type");
}

decimal totalAmount = transactionAmount + surchargeAmount;

4. Route Transaction Based on Card Type

BinResponse binInfo = await client.GetBinInfoAsync(bin);

if (binInfo.CardType == "Debit")
{
    // Route to debit network (lower fees)
    ProcessAsDebitTransaction(cardNumber);
}
else if (binInfo.CardType == "Credit")
{
    // Route to credit network
    ProcessAsCreditTransaction(cardNumber);
}

5. Show Bank Contact Information

// Display issuing bank information for customer service
BinResponse binInfo = await client.GetBinInfoAsync(bin);

if (binInfo.IssuerInformation != null)
{
    Console.WriteLine("If you have questions about this card, contact:");
    Console.WriteLine($"Bank: {binInfo.IssuerInformation.Name}");
    Console.WriteLine($"Phone: {binInfo.IssuerInformation.PhoneNumber}");
}

Best Practices

  • Use 8 digits when possible: 8-digit BINs provide more accurate results than 6-digit BINs
  • Cache BIN responses: BIN data rarely changes, so cache results for 24+ hours to reduce API calls
  • Lookup early: Call BIN lookup when user types first 6-8 digits, before they complete the full card number
  • Graceful fallbacks: If BIN lookup fails or returns "Unknown", continue with transaction (don't block the payment)
  • Privacy consideration: Don't log full card numbers, only BINs (first 6-8 digits are not considered sensitive)
  • Update card logos: Use BIN lookup to dynamically show the correct card brand logo
  • Respect surcharge rules: Always check the surcharge field before applying fees

BIN Lookup Timing

Option 1: As-You-Type Lookup

// When user has typed 6-8 digits, perform lookup
function onCardNumberChange(cardNumber) {
    if (cardNumber.length >= 8) {
        string bin = cardNumber.substring(0, 8);
        BinResponse binInfo = await GetBinInfoAsync(bin);

        // Update UI with card brand
        displayCardBrand(binInfo.BrandName);
    }
}

Option 2: Before Transaction

// Look up BIN right before processing transaction
string cardNumber = GetCardNumber();
string bin = ExtractBin(cardNumber, 8);
BinResponse binInfo = await GetBinInfoAsync(bin);

// Apply business rules based on BIN info
if (binInfo.Surcharge == "Allowed") {
    ApplySurcharge();
}

ProcessTransaction(cardNumber, totalAmount);

Troubleshooting

404 Not Found - BIN Not in Database

  • The BIN may be newly issued and not yet in the database
  • Try using 6 digits instead of 8 (some very new BINs may only have 6-digit data)
  • Continue with transaction - BIN lookup is informational, not required
  • Contact support if specific BINs consistently return 404

Response Returns "Unknown" for Card Type

  • BIN database may not have complete information for this card
  • Treat "Unknown" conservatively (e.g., assume surcharge is not allowed)
  • Allow transaction to proceed - don't block based on "Unknown" values

Different Results for 6 vs 8 Digits

  • 8-digit BINs are more specific and may return different information
  • Use 8 digits when available for most accurate results
  • Some card ranges may share the same 6-digit prefix but differ at 8 digits

Related Endpoints

  • GET /v1/rest/bins - Look up multiple BINs in a single request (bulk lookup)

Additional Notes

  • BIN databases are updated regularly as new card ranges are issued by banks
  • The first digit of a BIN indicates the card network (4=Visa, 5=Mastercard, 3=Amex/Discover, 6=Discover)
  • BIN information is considered non-sensitive data and can be safely logged or cached
  • Some very old cards may use 6-digit BINs; newer cards typically use 8-digit BINs
  • International cards may have less complete information in the database
  • The binId field is an internal identifier - you should use the bin field for the actual card prefix
  • BIN lookup does NOT validate whether a card number is real or active - it only identifies the card type and issuer