Skip to main content

Cards

The Card resource represents a debit card under an account.

Card creation request supports Idempotency, ensuring that performing multiple identical requests will have the same effect as performing a single request.

note

Unit enables you to programmatically review purchase Authorization Requests when they are made, and decide whether to approve the purchase. This capability gives complete control and visibility into card purchases.

Card Statuses#

Card have a Status Property, which represent their current status and determines what actions can or can't be completed using the card.

StatusDescriptionComments
InactiveThe Card has not been activated by the CustomerCards can be activated using the Activate card or by calling a the toll-free number printed on the card. Virtual cards do not require activation.
ActiveThe Card has been activated and can be used regularly
StolenThe Card has been reported stolen by the CustomerA stolen card cannot be reopened.
LostThe Card has been reported lost by the customerA lost card cannot be reopened.
FrozenThe Card has been frozen
ClosedByCustomerThe Card has been closed by the CustomerA closed card cannot be reopened.
SuspectedFraudThe Card has been flagged due to fraud suspicionCards are defined as "SuspectedFraud" by the card network (e.g. Visa). While in this status, the card cannot be used. The network will reach out to the client to clear out the fraud suspicion, and re-activate the card.
info

When a card (physical or virtual) is due to expire, The network will automatically re-issue a new card, with the same card number, different expiry and a new CVV. New physical cards will need to be activated by the customer.

Create Individual Debit Card#

Creates and ships a physical debit card to an individual. You must link the card to an account using the account field under relationships object. The linked account must belong to an individual customer (and not a business).

note

For security reasons, an individual customer's account may have up to one physical card in Active or newly created (Inactive) status. To change this policy in your org, please contact Unit. Cards that were reported lost, reported stolen or closed do not count as active.

VerbPOST
Urlhttps://api.s.unit.sh/cards
Required Scopecards-write
Data TypeindividualDebitCard

Attributes#

NameTypeDescription
shippingAddressAddressOptional. Address to ship the card to. If not specified, the individual address is used.
designstringOptional. You may omit if you only have one card design. Please contact Unit if you need multiple card designs.
additionalEmbossedTextstringOptional, up to 21 characters. Use for a second cardholder name, company name, or other data to be embossed on a card.
idempotencyKeystringOptional. See Idempotency.
tagsobjectOptional. See Tags.
limitsobjectOptional. See Limits.

Relationships#

NameTypeDescription
accountJSON:API RelationshipLink to the account the card belongs to. Holder of the account must be an individual.
customerJSON:API RelationshipOptional, Link to the customer the card belongs to. Mandatory if the account has more than one customer. Holder of the account must be an individual.
Example Request:
curl -X POST 'https://api.s.unit.sh/cards'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "individualDebitCard",    "attributes": {      "shippingAddress": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "idempotencyKey": "3a1a33be-4e12-4603-9ed0-820922389fb8",      "limits": {        "dailyWithdrawal": 50000,        "dailyPurchase": 50000,        "monthlyWithdrawal": 500000,        "monthlyPurchase": 700000      }    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "2"        }      }    }  }}'

Response#

Response is a JSON:API document.

201 Created#

FieldTypeDescription
dataIndividualDebitCardThe target resource after the operation was completed.
Example Response:
{  "data": {    "type": "individualDebitCard",    "id": "8",    "attributes": {      "createdAt": "2020-05-13T09:07:47.645Z",      "last4Digits": "1234",      "expirationDate": "2022-05",      "shippingAddress": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "status": "Inactive"    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "2"        }      },      "customer": {        "data": {          "type": "individualCustomer",          "id": "2"        }      }    }  }}

Create Business Debit Card#

Creates and ships a physical debit card to a business card holder. You must link the card to an account using the account field under relationships object. The linked account must belong to a business customer.

note

When creating a business debit card, the card holder's personal information must be provided as part of the request.

note

For security reasons, a card holder of a business debit card may have up to one physical card in Active or newly created (Inactive) status. To change this policy in your org, please contact Unit. Cards that were reported lost, reported stolen or closed do not count as active.

VerbPOST
Urlhttps://api.s.unit.sh/cards
Required Scopecards-write
Data TypebusinessDebitCard

Attributes#

NameTypeDescription
ssnstringOptional. SSN of the card holder (numbers only).
passportstringOptional. Passport number of the card holder.
nationalityISO31661-Alpha2 stringRequired on passport only. Two letters representing the card holder nationality. (e.g. "US").
fullNameFullNameFull name of the card holder.
dateOfBirthRFC3339 Date stringDate of birth of the card holder (e.g. "2001-08-15").
addressAddressAddress of the card holder.
shippingAddressAddressOptional. Address to ship the card to. If not specified, card holder address is used.
phonePhonePhone of the card holder.
emailstringEmail address of the card holder.
designstringOptional. You may omit if you only have one card design. Please contact Unit if you need multiple card designs.
additionalEmbossedTextstringOptional, up to 21 characters. Use for a second cardholder name, company name, or other data to be embossed on a card.
idempotencyKeystringOptional. See Idempotency.
tagsobjectOptional. See Tags.
limitsobjectOptional. See Limits.

Relationships#

NameTypeDescription
accountJSON:API RelationshipThe account the card belongs to. Holder of the account must be a business.
Example Request:
curl -X POST 'https://api.s.unit.sh/cards'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "businessDebitCard",    "attributes": {      "shippingAddress": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "fullName": {        "first": "Richard",        "last": "Hendricks"      },      "ssn": "123456789",      "address": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "dateOfBirth": "2001-08-10",      "email": "richard@piedpiper.com",      "phone": {        "countryCode": "1",        "number": "5555555555"      },      "idempotencyKey": "3a1a33be-4e12-4603-9ed0-820922389fb8",      "limits": {        "dailyWithdrawal": 50000,        "dailyPurchase": 50000,        "monthlyWithdrawal": 500000,        "monthlyPurchase": 700000      }    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "1"        }      }    }  }}'

Response#

Response is a JSON:API document.

201 Created#

FieldTypeDescription
dataBusinessDebitCardThe target resource after the operation was completed.
Example Response:
{  "data": {    "type": "businessDebitCard",    "id": "9",    "attributes": {      "createdAt": "2020-05-13T09:42:21.857Z",      "last4Digits": "2074",      "expirationDate": "2022-05",      "shippingAddress": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "address": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "fullName": {        "first": "Richard",        "last": "Hendricks"      },      "phone": {        "countryCode": "1",        "number": "5555555666"      },      "email": "richard@piedpiper.com",      "dateOfBirth": "2001-08-10",      "ssn": "123456789",      "status": "Inactive"    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "1"        }      },      "customer": {        "data": {          "type": "businessCustomer",          "id": "1"        }      }    }  }}

Create Individual Virtual Debit Card#

Creates a debit card for an individual. You must link the card to an account using the account field under relationships object. The linked account must belong to an individual customer (and not a business).

note

For security reasons, an individual customer's account may have up to one virtual card in Active status. To change this policy in your org, please contact Unit. Cards that were reported lost, reported stolen or closed do not count as active.

note

Unlike physical cards, virtual cards are created in Active status and do not require activation.

VerbPOST
Urlhttps://api.s.unit.sh/cards
Required Scopecards-write
Data TypeindividualVirtualDebitCard

Attributes#

NameTypeDescription
idempotencyKeystringOptional. See Idempotency.
tagsobjectOptional. See Tags.
LimitsobjectOptional. See Limits.

Relationships#

NameTypeDescription
accountJSON:API RelationshipLink to the account the card belongs to. Holder of the account must be an individual.
customerJSON:API RelationshipOptional, Link to the customer the card belongs to. Mandatory if the account has more than one customer. Holder of the account must be an individual.
Example Request:
curl -X POST 'https://api.s.unit.sh/cards'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "individualVirtualDebitCard",    "attributes": {      "idempotencyKey": "3a1a33be-4e12-4603-9ed0-820922389fb8",      "limits": {        "dailyWithdrawal": 50000,        "dailyPurchase": 50000,        "monthlyWithdrawal": 500000,        "monthlyPurchase": 700000      }    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "2"        }      }    }  }}'

Response#

Response is a JSON:API document.

201 Created#

FieldTypeDescription
dataIndividualVirtualDebitCardThe target resource after the operation was completed.
Example Response:
{  "data": {    "type": "individualVirtualDebitCard",    "id": "8",    "attributes": {      "createdAt": "2020-05-13T09:07:47.645Z",      "last4Digits": "1234",      "expirationDate": "2022-05",      "status": "Active"    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "2"        }      },      "customer": {        "data": {          "type": "individualCustomer",          "id": "2"        }      }    }  }}

Create Business Virtual Debit Card#

Creates a debit card for a business. You must link the card to an account using the account field under relationships object. The linked account must belong to a business customer.

note

When creating a business debit card, the card holder's personal information must be provided as part of the request.

note

For security reasons, a card holder of a business debit card may have up to one virtual card in Active or newly created (Inactive) status. To change this policy in your org, please contact Unit. Cards that were reported lost, reported stolen or closed do not count as active.

note

Unlike physical cards, virtual cards are created in Active status and do not require activation.

VerbPOST
Urlhttps://api.s.unit.sh/cards
Required Scopecards-write
Data TypebusinessVirtualDebitCard

Attributes#

NameTypeDescription
ssnstringOptional. SSN of the card holder (numbers only).
passportstringOptional. Passport number of the card holder.
nationalityISO31661-Alpha2 stringRequired on passport only. Two letters representing the card holder nationality. (e.g. "US").
fullNameFullNameFull name of the card holder.
dateOfBirthRFC3339 Date stringDate of birth of the card holder (e.g. "2001-08-15").
addressAddressAddress of the card holder.
phonePhonePhone of the card holder.
emailstringEmail address of the card holder.
idempotencyKeystringOptional. See Idempotency.
tagsobjectOptional. See Tags.
limitsobjectOptional. See Limits.

Relationships#

NameTypeDescription
accountJSON:API RelationshipThe account the card belongs to. Holder of the account must be a business.
Example Request:
curl -X POST 'https://api.s.unit.sh/cards'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "businessVirtualDebitCard",    "attributes": {      "fullName": {        "first": "Richard",        "last": "Hendricks"      },      "ssn": "123456789",      "address": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "dateOfBirth": "2001-08-10",      "email": "richard@piedpiper.com",      "phone": {        "countryCode": "1",        "number": "5555555555"      },      "idempotencyKey": "3a1a33be-4e12-4603-9ed0-820922389fb8",      "limits": {        "dailyWithdrawal": 50000,        "dailyPurchase": 50000,        "monthlyWithdrawal": 500000,        "monthlyPurchase": 700000      }    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "1"        }      }    }  }}'

Response#

Response is a JSON:API document.

201 Created#

FieldTypeDescription
dataBusinessVirtualDebitCardThe target resource after the operation was completed.
Example Response:
{  "data": {    "type": "businessVirtualDebitCard",    "id": "9",    "attributes": {      "createdAt": "2020-05-13T09:42:21.857Z",      "last4Digits": "2074",      "expirationDate": "2022-05",      "address": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "fullName": {        "first": "Richard",        "last": "Hendricks"      },      "phone": {        "countryCode": "1",        "number": "5555555666"      },      "email": "richard@piedpiper.com",      "dateOfBirth": "2001-08-10",      "ssn": "123456789",      "status": "Active"    },    "relationships": {      "account": {        "data": {          "type": "depositAccount",          "id": "1"        }      },      "customer": {        "data": {          "type": "businessCustomer",          "id": "1"        }      }    }  }}

Displaying Sensitive Card Data#

In order to display sensitive card data (card number and CVV2) to a customer, without any of it passing through your systems (which would subject you to PCI compliance requirements), Unit utilizes a 3rd party service called Very Good Security or VGS for short.

note

Displaying card number and CVV2 is only available for virtual cards.

VGS provides a JavaScript library (as well as iOS and Android SDKs) called VGS Show which allows easy integration with your UI components. VGS Show offloads the PCI compliance burden by enabling the encrypted transmission of sensitive card data from VGS directly to your cardholder.

The VGS Show JavaScript library enables you to securely display sensitive data in a webpage while safely isolating that sensitive data from your systems. VGS Show JavaScript library injects a secure iframe into your HTML. VGS hosts both the iframe, and the data on secure, compliant servers.

Integration steps#

Import the VGS Show library:

<script type="text/javascript" src="https://js.verygoodvault.com/vgs-show/1.3/ACh8JJTM42LYxwe2wfGQxwj5.js"></script>

Initialize the component:

const show = VGSShow.create('tntazhyknp1');

note

The Vault Id tntazhyknp1 enables you to test your code in a sandbox environment. Contact Unit for the live Vault Id.

Provide a valid customer token:

const customerToken = "<CUSTOMER TOKEN>"

For instructions, see Create Customer Token.

caution

The customer token is required to include the cards-sensitive scope. Unit recommends avoiding adding additional scopes to the token.

Provide a valid card identifier

path: '/cards/<CARD ID>/secure-data/cvv2'

Example of creating a Customer Token for sensitive data:
curl -X POST 'https://api.s.unit.sh/customers/8/token'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "customerToken",    "attributes": {      "scope": "cards-sensitive",      "verificationToken": "i8FWKLBjXEg3TdeK93G3K9PKLzhbT6CRhn/VKkTsm....",      "verificationCode": "203130"    }  }}'

Additional resources#

SDKs for iOS and Android and additional code examples can be found here.

Example of displaying card number and CVV2:
<!DOCTYPE html><html><head>    <meta charSet="utf-8">    <title></title>    <style>        iframe {            height: 20px;        }    </style></head><body><h2>Sensitive Data example</h2><label>Card Number:</label><div id="cardNumber"></div><label>CVV2:</label><div id="cvv2"></div>
<script type="text/javascript" src="https://js.verygoodvault.com/vgs-show/1.3/ACh8JJTM42LYxwe2wfGQxwj5.js"></script><script type="text/javascript">    const show = VGSShow.create('tntazhyknp1');    const customerToken = "<CUSTOMER TOKEN>"
    const cvv2iframe = show.request({            name: 'data-text',            method: 'GET',            path: '/cards/<CARD ID>/secure-data/cvv2',            headers: {                "Authorization": "Bearer " + customerToken            },            htmlWrapper: 'text',            jsonPathSelector: 'data.attributes.cvv2'        });    cvv2iframe.render('#cvv2');
    const cardNumberIframe = show.request({            name: 'data-text',            method: 'GET',            path: '/cards/<CARD ID>/secure-data/pan',            headers: {                "Authorization": "Bearer " + customerToken            },            htmlWrapper: 'text',            jsonPathSelector: 'data.attributes.pan'        });    cardNumberIFrame.render('#cardNumber');</script></body></html>

Activate Card#

In order to activate a new card, without any sensitive data passing through your systems (which requires PCI compliance), Unit utilizes a 3rd party service called Very Good Security or VGS for short.

VGS provides a JavaScript library (as well as iOS and Android SDKs) called VGS Collect which allows easy integration with your UI components. VGS Collect offloads the PCI compliance burden by enabling the encrypted transmission of sensitive card data from VGS directly to the card processor.

VGS Collect JavaScript library injects a secure iframe into your HTML. VGS hosts both the iframe, and the data on secure, compliant servers.

note

Unlike physical cards, virtual cards are created in Active status and do not require activation.

Integration steps#

Import the VGS Collect library:

<script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.9.0/vgs-collect.js"></script>

Initialize the component:

const form = VGSCollect.create("tntazhyknp1", "sandbox", function(state) {});

note

The Vault Id tntazhyknp1 enables you to test your code in a sandbox environment. Contact Unit for the live Vault Id.

Provide a valid customer token:

const customerToken = "<CUSTOMER TOKEN>"

For instructions, see Create Customer Token.

caution

The customer token is required to include the cards-sensitive-write scope. Unit recommends avoiding adding additional scopes to the token.

Provide a valid card identifier:

path: '/cards/<CARD ID>/activate'

Required field names and formats:

  • CVV2 field name should be data.attributes.cvv2.
  • Expiration Date field name should be data.attributes.expirationDate.
  • Expiration Date field format should be YYYY-MM.

Testing on Sandbox:

  • To simulate the scenario where the customer provides invalid data - send 1970-01 as the expiration date.
  • Sending anything other than that will result in a successful card activation.
Example of creating a Customer Token for Activate Card:
curl -X POST 'https://api.s.unit.sh/customers/8/token'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "customerToken",    "attributes": {      "scope": "cards-sensitive-write",      "verificationToken": "i8FWKLBjXEg3TdeK93G3K9PKLzhbT6CRhn/VKkTsm....",      "verificationCode": "203130"    }  }}'

Additional resources#

SDKs for iOS and Android and additional code examples can be found here.

Example of Activate Card:
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>VGS Collect Credit Card Example</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.9.0/vgs-collect.js"></script>
    <style>        body {            padding: 25px;        }
        span[id*="cc-"] {            display: block;            height: 40px;            margin-bottom: 15px;        }
        span[id*="cc-"] iframe {            height: 100%;            width: 100%;        }
        pre {            font-size: 12px;        }
        .form-field {            display: block;            width: 100%;            height: calc(2.25rem + 2px);            padding: .375rem .75rem;            font-size: 1rem;            line-height: 1.5;            color: #495057;            background-color: #fff;            background-clip: padding-box;            border: 1px solid #ced4da;            border-radius: .25rem;            transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;        }
        .form-field iframe {            border: 0 none transparent;            height: 100%;            vertical-align: middle;            width: 100%;        }
        p {            margin-bottom: 10px;        }    </style></head><body><main>    <div class="row">        <div class="col-md-4"></div>        <div class="col-md-4">            <div class="row card card-outline-secondary">                <div class="card-body">                    <h3 class="text-center">Activate Card</h3>                    <hr>                    <div class="alert alert-info p-2">                        Please fill in and submit the form                    </div>                    <form id="cc-form">                        <div class="form-group">                            <label for="cc-cvv2">CVV2</label>                            <span id="cc-cvv2" class="form-field">                  <!--VGS Collect iframe for CVV2 field will be here!-->                </span>                            <label for="cc-expiration-date">Expiration Date</label>                            <span id="cc-expiration-date" class="form-field">                  <!--VGS Collect iframe for Expiration Date field will be here!-->                </span>                        </div>                        <!--Submit form button-->                        <button type="submit" class="btn btn-success btn-block">Submit</button>                    </form>                </div>            </div>        </div>        <div class="col-md-4"></div>    </div></main>
<!--Include script with VGS Collect form initialization--><script>    // VGS Collect form initialization    const form = VGSCollect.create("tntazhyknp1", "sandbox", function(state) {});    const customerToken = "<CUSTOMER TOKEN>"
    form.field('#cc-cvv2', {        type: 'card-security-code',        name: 'data.attributes.cvv2',        successColor: '#4F8A10',        errorColor: '#D8000C',        placeholder: '123',        maxLength: 3,        validations: ['required', 'validCardSecurityCode']    });
    form.field('#cc-expiration-date', {        type: 'card-expiration-date',        name: 'data.attributes.expirationDate',        successColor: '#4F8A10',        errorColor: '#D8000C',        placeholder: 'MM / YYYY',        validations: ['required', 'validCardExpirationDate'],        // Change to required experiation date format        serializers: [form.SERIALIZERS.replace('(\\d{2})\\s\\/\\s(\\d{4})', '$2-$1')]    });
    // Submit by executing a POST request.    document.getElementById('cc-form')        .addEventListener('submit', function(e) {            e.preventDefault();            form.submit('/cards/<CARD ID>/activate',                {                    // This converts the dot-separated field name strings into a JSON object                    mapDotToObject: 'true',                    headers: {                        "Content-Type": "application/vnd.api+json",                        "Authorization": "Bearer " + customerToken                    }                },

                function(status, data) {                    console.log(data);                });        }, function (errors) {            console.log(errors);        });</script></body></html>

Get PIN Status#

Gets the PIN status for the specified card.

If the returned status is NotSet, use Set PIN, otherwise use Change PIN.

VerbGET
Urlhttps://api.s.unit.sh/cards/{id}/secure-data/pin/status
Required Scopecards or cards-sensitive

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataPinStatusPinStatus resource.
curl -X GET 'https://api.s.unit.sh/cards/5/secure-data/pin/status' \-H "Authorization: Bearer ${TOKEN}"

Set PIN#

In order to set a new PIN, without any sensitive data passing through your systems (which requires PCI compliance), Unit utilizes a 3rd party service called Very Good Security or VGS for short.

VGS provides a JavaScript library (as well as iOS and Android SDKs) called VGS Collect which allows easy integration with your UI components. VGS Collect offloads the PCI compliance burden by enabling the encrypted transmission of sensitive card data from VGS directly to the card processor.

VGS Collect JavaScript library injects a secure iframe into your HTML. VGS hosts both the iframe, and the data on secure, compliant servers.

Integration steps#

Import the VGS Collect library:

<script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.9.0/vgs-collect.js"></script>

Initialize the component:

const form = VGSCollect.create("tntazhyknp1", "sandbox", function(state) {});

note

The Vault Id tntazhyknp1 enables you to test your code in a sandbox environment. Contact Unit for the live Vault Id.

Provide a valid customer token:

const customerToken = "<CUSTOMER TOKEN>"

For instructions, see Create Customer Token.

caution

The customer token is required to include the cards-sensitive-write scope. Unit recommends avoiding adding additional scopes to the token.

Provide a valid card identifier:

path: '/cards/<CARD ID>/secure-data/pin'

Required field names and formats:

  • PIN field name should be data.attributes.pin.
Example of creating a Customer Token for Set PIN:
curl -X POST 'https://api.s.unit.sh/customers/8/token'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "customerToken",    "attributes": {      "scope": "cards-sensitive-write",      "verificationToken": "i8FWKLBjXEg3TdeK93G3K9PKLzhbT6CRhn/VKkTsm....",      "verificationCode": "203130"    }  }}'

Additional resources#

SDKs for iOS and Android and additional code examples can be found here.

Example of Set PIN:
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Set PIN Example</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.9.0/vgs-collect.js"></script>
    <style>        body {            padding: 25px;        }
        span[id*="cc-"] {            display: block;            height: 40px;            margin-bottom: 15px;        }
        span[id*="cc-"] iframe {            height: 100%;            width: 100%;        }
        pre {            font-size: 12px;        }
        .form-field {            display: block;            width: 100%;            height: calc(2.25rem + 2px);            padding: .375rem .75rem;            font-size: 1rem;            line-height: 1.5;            color: #495057;            background-color: #fff;            background-clip: padding-box;            border: 1px solid #ced4da;            border-radius: .25rem;            transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;        }
        .form-field iframe {            border: 0 none transparent;            height: 100%;            vertical-align: middle;            width: 100%;        }
        p {            margin-bottom: 10px;        }    </style></head><body><main>    <div class="row">        <div class="col-md-4"></div>        <div class="col-md-4">            <div class="row card card-outline-secondary">                <div class="card-body">                    <h3 class="text-center">Set PIN</h3>                    <hr>                    <div class="alert alert-info p-2">                        Please fill in and submit the form                    </div>                    <form id="cc-form">                        <div class="form-group">                            <label for="cc-pin">PIN</label>                            <span id="cc-pin" class="form-field">                  <!--VGS Collect iframe for PIN field will be here!-->                </span>                        </div>                        <!--Submit form button-->                        <button type="submit" class="btn btn-success btn-block">Submit</button>                    </form>                </div>            </div>        </div>        <div class="col-md-4"></div>    </div></main>
<!--Include script with VGS Collect form initialization--><script>    // VGS Collect form initialization    const form = VGSCollect.create("tntazhyknp1", "sandbox", function(state) {});    const customerToken = "<CUSTOMER TOKEN>"
    // Create VGS Collect field for PIN    form.field('#cc-pin', {        type: 'text',        name: 'data.attributes.pin',        successColor: '#4F8A10',        errorColor: '#D8000C',        placeholder: '1234',        maxLength: 6,        validations: ['required', '/^([0-9]{4,6})$/'],    });
    // Submit by executing a POST request.    document.getElementById('cc-form')        .addEventListener('submit', function(e) {            e.preventDefault();            form.submit('/cards/<CARD ID>/secure-data/pin',                {                    // This converts the dot-separated field name string into a JSON object                    mapDotToObject: 'true',                    headers: {                        "Content-Type": "application/vnd.api+json",                        "Authorization": "Bearer " + customerToken                    }                },

                function(status, data) {                    console.log(data);                });        }, function (errors) {            console.log(errors);        });</script></body></html>

Change PIN#

In order to change an existing PIN, without any sensitive data passing through your systems (which requires PCI compliance), Unit utilizes a 3rd party service called Very Good Security or VGS for short.

VGS provides a JavaScript library (as well as iOS and Android SDKs) called VGS Collect which allows easy integration with your UI components. VGS Collect offloads the PCI compliance burden by enabling the encrypted transmission of sensitive card data from VGS directly to the card processor.

VGS Collect JavaScript library injects a secure iframe into your HTML. VGS hosts both the iframe, and the data on secure, compliant servers.

Integration steps#

Import the VGS Collect library:

<script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.9.0/vgs-collect.js"></script>

Initialize the component:

const form = VGSCollect.create("tntazhyknp1", "sandbox", function(state) {});

note

The Vault Id tntazhyknp1 enables you to test your code in a sandbox environment. Contact Unit for the live Vault Id.

Provide a valid customer token:

const customerToken = "<CUSTOMER TOKEN>"

For instructions, see Create Customer Token.

caution

The customer token is required to include the cards-sensitive-write scope. Unit recommends avoiding adding additional scopes to the token.

Provide a valid card identifier:

path: '/cards/<CARD ID>/secure-data/pin'

Required field names and formats:

  • Old PIN field name should be data.attributes.oldPin.
  • New PIN field name should be data.attributes.newPin.
Example of creating a Customer Token for Change PIN:
curl -X POST 'https://api.s.unit.sh/customers/8/token'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "customerToken",    "attributes": {      "scope": "cards-sensitive-write",      "verificationToken": "i8FWKLBjXEg3TdeK93G3K9PKLzhbT6CRhn/VKkTsm....",      "verificationCode": "203130"    }  }}'

Additional resources#

SDKs for iOS and Android and additional code examples can be found here.

Example of Change PIN:
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Change PIN Example</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.9.0/vgs-collect.js"></script>
    <style>        body {            padding: 25px;        }
        span[id*="cc-"] {            display: block;            height: 40px;            margin-bottom: 15px;        }
        span[id*="cc-"] iframe {            height: 100%;            width: 100%;        }
        pre {            font-size: 12px;        }
        .form-field {            display: block;            width: 100%;            height: calc(2.25rem + 2px);            padding: .375rem .75rem;            font-size: 1rem;            line-height: 1.5;            color: #495057;            background-color: #fff;            background-clip: padding-box;            border: 1px solid #ced4da;            border-radius: .25rem;            transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;        }
        .form-field iframe {            border: 0 none transparent;            height: 100%;            vertical-align: middle;            width: 100%;        }
        p {            margin-bottom: 10px;        }    </style></head><body><main>    <div class="row">        <div class="col-md-4"></div>        <div class="col-md-4">            <div class="row card card-outline-secondary">                <div class="card-body">                    <h3 class="text-center">Change PIN</h3>                    <hr>                    <div class="alert alert-info p-2">                        Please fill in and submit the form                    </div>                    <form id="cc-form">                        <div class="form-group">                            <label for="cc-old-pin">Old PIN</label>                            <span id="cc-old-pin" class="form-field">                  <!--VGS Collect iframe for Old PIN field will be here!-->                </span>                        </div>                        <div class="form-group">                            <label for="cc-new-pin">New PIN</label>                            <span id="cc-new-pin" class="form-field">                  <!--VGS Collect iframe for New PIN field will be here!-->                </span>                        </div>                        <!--Submit form button-->                        <button type="submit" class="btn btn-success btn-block">Submit</button>                    </form>                </div>            </div>        </div>        <div class="col-md-4"></div>    </div></main>
<!--Include script with VGS Collect form initialization--><script>    // VGS Collect form initialization    const form = VGSCollect.create("tntazhyknp1", "sandbox", function(state) {});    const customerToken = "<CUSTOMER TOKEN>"
    // Create VGS Collect field for Old PIN    form.field('#cc-old-pin', {        type: 'text',        name: 'data.attributes.oldPin',        successColor: '#4F8A10',        errorColor: '#D8000C',        placeholder: '1234',        maxLength: 6,        validations: ['required', '/^([0-9]{4,6})$/'],    });
    // Create VGS Collect field for New PIN    form.field('#cc-new-pin', {        type: 'text',        name: 'data.attributes.newPin',        successColor: '#4F8A10',        errorColor: '#D8000C',        placeholder: '1234',        maxLength: 6,        validations: ['required', '/^([0-9]{4,6})$/'],    });
    // Submit by executing a PUT request.    document.getElementById('cc-form')        .addEventListener('submit', function(e) {            e.preventDefault();            form.submit('/cards/10001/secure-data/pin',                {                    method: 'PUT',                    mapDotToObject: 'true',                    headers: {                        "Content-Type": "application/vnd.api+json",                        "Authorization": "Bearer " + customerToken                    }                },

                function(status, data) {                    console.log(data);                });        }, function (errors) {            console.log(errors);        });</script></body></html>

Report Stolen#

Report card as stolen.

VerbPOST
Urlhttps://api.s.unit.sh/cards/:cardId/report-stolen
Required Scopecards-write

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataIndividualDebitCard or BusinessDebitCard or IndividualVirtualDebitCard or BusinessVirtualDebitCardCard resource, distinguished by the type field.
curl -X POST 'https://api.s.unit.sh/cards/6/report-stolen' \-H "Authorization: Bearer ${TOKEN}"

Report Lost#

Report card as lost.

VerbPOST
Urlhttps://api.s.unit.sh/cards/:cardId/report-lost
Required Scopecards-write

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataIndividualDebitCard or BusinessDebitCard or IndividualVirtualDebitCard or BusinessVirtualDebitCardCard resource, distinguished by the type field.
curl -X POST 'https://api.s.unit.sh/cards/5/report-lost' \-H "Authorization: Bearer ${TOKEN}"

Close Card#

Close a card.

VerbPOST
Urlhttps://api.s.unit.sh/cards/:cardId/close
Required Scopecards-write

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataIndividualDebitCard or BusinessDebitCard or IndividualVirtualDebitCard or BusinessVirtualDebitCardCard resource, distinguished by the type field.
curl -X POST 'https://api.s.unit.sh/cards/7/close' \-H "Authorization: Bearer ${TOKEN}"

Freeze Card#

Freeze a card (temporarily block a card).

VerbPOST
Urlhttps://api.s.unit.sh/cards/:cardId/freeze
Required Scopecards-write

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataIndividualDebitCard or BusinessDebitCard or IndividualVirtualDebitCard or BusinessVirtualDebitCardCard resource, distinguished by the type field.
curl -X POST 'https://api.s.unit.sh/cards/8/freeze' \-H "Authorization: Bearer ${TOKEN}"

Unfreeze Card#

Unfreeze a frozen card.

VerbPOST
Urlhttps://api.s.unit.sh/cards/:cardId/unfreeze
Required Scopecards-write

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataIndividualDebitCard or BusinessDebitCard or IndividualVirtualDebitCard or BusinessVirtualDebitCardCard resource, distinguished by the type field.
curl -X POST 'https://api.s.unit.sh/cards/8/unfreeze' \-H "Authorization: Bearer ${TOKEN}"

Replace Card#

Creates and ships a replacement physical debit card to an individual or business card holder. The replacement card has the same card number, expiration date and PIN as the original card, and does not require activation.

note

A card that was closed or reported lost or stolen cannot be replaced and a new card should be created instead.

VerbPOST
Urlhttps://api.s.unit.sh/cards/:cardId/replace
Required Scopecards-sensitive-write or cards-write
Data TypereplaceCard

Attributes#

NameTypeDescription
shippingAddressAddressAddress to ship the card to. Optional, if not specified, the address provided during card creation is reused.
Example Request:
curl -X POST 'https://api.s.unit.sh/cards/8/replace'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "replaceCard",    "attributes": {      "shippingAddress": {        "street": "5230 Newell Rd",        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      }    }  }}'

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataIndividualDebitCard or BusinessDebitCardCard resource, distinguished by the type field.
Example Response:
{  "data": {    "type": "individualDebitCard",    "id": "8",    "attributes": {      "createdAt": "2020-05-13T09:07:47.645Z",      "last4Digits": "1234",      "expirationDate": "2022-05",      "shippingAddress": {        "street": "5230 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94303",        "country": "US"      },      "status": "Inactive"    },    "relationships": {      "account": {        "data": {          "type": "account",          "id": "2"        }      },      "customer": {        "data": {          "type": "customer",          "id": "2"        }      }    }  }}

Get by Id#

Get a card resource by id.

VerbGET
Urlhttps://api.s.unit.sh/cards/{id}
Required Scopecards

Query Parameters#

NameTypeDefaultDescription
includestring(empty)Optional. A comma-separated list of related resources to include in the response. Related resources include: customer, account. See Getting Related Resources

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataIndividualDebitCard or BusinessDebitCard or IndividualVirtualDebitCard or BusinessVirtualDebitCardCard resource, distinguished by the type field.
includedArray of DepositAccount or CustomerArray of resources requested by the include query parameter.
curl -X GET 'https://api.s.unit.sh/cards/1?include=customer' \-H "Authorization: Bearer ${TOKEN}"

List#

List cards. Filtering and paging can be applied.

VerbGET
Urlhttps://api.s.unit.sh/cards
Required Scopecards

Query Parameters#

NameTypeDefaultDescription
page[limit]integer100Optional. Maximum number of resources that will be returned. Maximum is 1000 resources. See Pagination.
page[offset]integer0Optional. Number of resources to skip. See Pagination.
filter[accountId]string(empty)Optional. Filters the results by the specified account id.
filter[customerId]string(empty)Optional. Filters the results by the specified customer id.
filter[tags]Tags (JSON)(empty)Optional. Filter Cards by Tags.
includestring(empty)Optional. A comma-separated list of related resources to include in the response. Related resources include: customer, account. See Getting Related Resources
curl -X GET 'https://api.s.unit.sh/cards?page[limit]=20&page[offset]=0&include=customer' \-H "Authorization: Bearer ${TOKEN}"

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataArray of IndividualDebitCard or BusinessDebitCard or IndividualVirtualDebitCard or BusinessVirtualDebitCardArray of card resources, distinguished by the type field.
includedArray of DepositAccount or CustomerArray of resources requested by the include query parameter.
Example Response:
{  "data": [    {      "type": "individualDebitCard",      "id": "1",      "attributes": {        "createdAt": "2020-05-10T16:45:02.272Z",        "last4Digits": "1234",        "expirationDate": "2022-05",        "status": "Active"      },      "relationships": {        "account": {          "data": {            "type": "depositAccount",            "id": "1"          }        },        "customer": {          "data": {            "type": "individualCustomer",            "id": "2"          }        }      }    },    {      "type": "businessDebitCard",      "id": "4",      "attributes": {        "createdAt": "2020-05-10T20:37:48.069Z",        "last4Digits": "1234",        "expirationDate": "2022-05",        "shippingAddress": {          "street": "5230 Newell Rd",          "street2": null,          "city": "Palo Alto",          "state": "CA",          "postalCode": "94303",          "country": "US"        },        "address": {          "street": "5230 Newell Rd",          "street2": null,          "city": "Palo Alto",          "state": "CA",          "postalCode": "94303",          "country": "US"        },        "fullName": {          "first": "Richard",          "last": "Hendricks"        },        "phone": {          "countryCode": "1",          "number": "5555555789"        },        "email": "richard@piedpiper.com",        "dateOfBirth": "2001-08-10",        "ssn": "123456789",        "status": "Active"      },      "relationships": {        "account": {          "data": {            "type": "depositAccount",            "id": "1"          }        },        "customer": {          "data": {            "type": "businessCustomer",            "id": "1"          }        }      }    }  ]}

Update#

Update a debit card.

VerbPATCH
Urlhttps://api.s.unit.sh/cards/:cardId
Required Scopecards-write

Update Individual Debit Card#

NameTypeDescription
shippingAddressAddressOptional. Address to ship the card to.
To modify or add specify the key and value.
To delete a key specify the key name and null for the value.
designstringOptional. Card design name. To modify or add specify the key and value.
tagsobjectOptional. See Updating Tags.
limitsobjectOptional. See Limits.

Update Business Debit Card#

NameTypeDescription
shippingAddressAddressOptional. Address to ship the card to.
To modify or add specify the key and value.
To delete a key specify the key name and null for the value.
addressAddressOptional. Address of the card holder.
To modify or add specify the new address.
phonePhoneOptional. Phone of the card holder.
To modify or add specify the new phone number.
emailstringOptional. Email address of the card holder.
To modify or add specify the new email address.
designstringOptional. Card design name. To modify or add specify the key and value.
tagsobjectOptional. See Updating Tags.
limitsobjectOptional. See Limits.

Update Individual Virtual Debit Card#

NameTypeDescription
tagsobjectOptional. See Updating Tags.
limitsobjectOptional. See Limits.

Update Business Virtual Debit Card#

NameTypeDescription
addressAddressOptional. Address of the card holder.
To modify or add specify the new address.
phonePhoneOptional. Phone of the card holder.
To modify or add specify the new phone number.
emailstringOptional. Email address of the card holder.
To modify or add specify the new email address.
tagsobjectOptional. See Updating Tags.
limitsobjectOptional. See Limits.

Response#

Response is a JSON:API document.

200 OK#

FieldTypeDescription
dataIndividualDebitCard Or BusinessDebitCard Or
BusinessVirtualDebitCard Or IndividualVirtualDebitCard resource
The target resource after the operation was completed.
Example of update business debit card:
curl -X PATCH 'https://api.s.unit.sh/cards/:cardId'-H 'Content-Type: application/vnd.api+json'-H 'Authorization: Bearer ${TOKEN}'--data-raw '{  "data": {    "type": "businessDebitCard",    "attributes": {      "shippingAddress": {        "street": "5231 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94301",        "country": "US"      },      "address": {        "street": "5231 Newell Rd",        "street2": null,        "city": "Palo Alto",        "state": "CA",        "postalCode": "94301",        "country": "US"      },      "email": "richard@piedpiper.com",      "phone": {        "countryCode": "1",        "number": "5555555556"      }    }  }}'

Limits#

VerbGET
Urlhttps://api.s.unit.sh/cards/:cardId/limits
curl -X GET 'https://api.s.unit.sh/cards/10104/limits' \-H "Authorization: Bearer ${TOKEN}"

Card purchases and withdrawals can be subjected daily and monthly amount limits. Limits are optional (by default there are no card-specific limits), and can be set when the card is created or updated. The limits are enforced by Unit, and once the limit is reached, the transaction will be rejected.

The daily limits are reset at 7:00 p.m. EST. The monthly limits are reset on the first of each month. We provide an API to query the current limits and daily/monthly totals for a card. Card limits can be updated through card update API.

info

Card level limits are used to allow more granular control and flexibility. The account limits on card activity are still enforced, across all cards that belong to a certain account.

{  "data": {    "type": "limits",    "attributes": {      "limits": {        "dailyWithdrawal": 100000,        "dailyPurchase": 200000,        "monthlyWithdrawal": 5000000,        "monthlyPurchase": 7000000      },      "dailyTotals": {        "withdrawals": 3000,        "deposits": 0,        "purchases": 4000      },      "monthlyTotals": {        "withdrawals": 120000,        "deposits": 0,        "purchases": 1400000      }    }  }}