Custodians (companies and developers) integrate with the Shift API to create and manage branded debit cards and cardholder data. We've tried to make this documentation user-friendly and example-filled, but please drop us a line with any questions. If you're planning to use our API in production, you should take a look at Metropolitan Commercial Bank's privacy policy.
When a cardholder uses his or her Shift Card to purchase goods or services, Shift's software must quickly confirm the cardholder has sufficient funds prior to authorizing the transaction. A cardholder's spendable balance can be exposed from a custodian's API -or- mainly reside within Shift.
Custodian API provides spendable balance acting as the infallible balance authority. In this case, Shift will request the user's current spendable balance from the custodian's API (your software). Shift will perform basic performance testing of your API prior to launch. Please reach out to Shift Support to discuss integration specifics.
-OR-
Shift stores a spendable balance for each cardholder. Your service simply updates each cardholder spendable balance as it changes within your business logic by consuming Shift's Cardholder Balances.
The Shift API is architected around REST, using standard HTTP verbs to communicate and HTTP response codes to indicate status and errors. All responses come in standard JSON. The Shift API is served over HTTPS to ensure data privacy; HTTP is not supported. Every request must include your secret API key. Request data must be included in the body.
API Endpoint
https://api.shiftpayments.com
Authentication
Authentication to the API occurs via HTTP Basic Auth. Provide your API publishable key as the basic auth username and the your API secret key as the password.
Live mode and testing
Every account is divided into two universes: one for testing, and one for running on your live website. All API requests exist in one of those two universes, and objects in one universe cannot be manipulated by objects in the other.
status code 401
{
"error": {
"type": "invalid_request_error",
"message": "Authentication to the API occurs via HTTP Basic Auth"
}
}
status code 400
{
"error": {
"type": "invalid_request_error",
"message": "Invalid region provided (must be US two letter state)"
}
}
Use the /cardholders
endpoint to create and manage Shift cardholders. Cardholder objects allow you to track application status and confirm basic customer info. You can retrieve individual cardholders as well as a list of all your cardholders.
Each cardholder object inlcudes a kyc_status
. This represents the current state of a user's 'Know Your Customer' identity verification process. More context around a cardholder's kyc_status
is provided with specific (and separate) reason groups.
KYC key | Potential Values |
---|---|
kyc_status | RESUBMIT_DETAILS , UPLOAD_FILE , UNDER_REVIEW , PASSED , REJECTED , TEMPORARY_ERROR |
kyc_identity_reason | null , WATCHLIST_MATCH , SSN_MISMATCH , SSN_INVALID |
kyc_address_reason | null , ADDRESS_COMMERCIAL , ADDRESS_PO_BOX , ADDRESS_RISKY |
kyc_file_reason | null , UNRELATED_FILE , WRONG_FILE , BLURRY |
KYC reasons will all have a null
value when kyc_status
is PASSED
POST /cardholders
In test mode:
- New users and cards are created but cards are not physically shipped and will not work over the Visa network.
- kyc_status is returned as
PASSED
when the last 4 digits of the provided SSN are '0000'.
Arguments
Parameter | Type | Details |
---|---|---|
first_name | required | |
last_name | required | |
required | ||
phone_number | required | E.164 number formatting |
address | required | International address object |
date_of_birth | required | ISO8601 Date format |
document | required | Identity document object |
custodian_uid | optional | Unique identifier of custodian's user |
design_key | optional | Shift card design key string |
Example Request Body
{
"first_name": "Josh",
"last_name": "Wilson",
"custodian_uid": "your-external-user-id",
"email": "pat@wilson.com",
"phone_number": "6157915911",
"date_of_birth": "1982-06-20",
"design_key": "blue",
"address": {
"street_one": "1800 Gates Ave",
"street_two": "2L",
"locality": "Ridgewood",
"region": "NY",
"postal_code": "11385",
"country": "USA"
},
"document": {
"type": "SSN",
"value": "490940000"
}
}
Example Response:
status code 200
{
"cardholder": {
"livemode": false,
"id": "crdhldr_1cd68f70917cb5ed",
"email": "pat@wilson.com",
"kyc_passed_at": "2016-10-19T23:20:21.034+00:00",
"kyc_status": "PASSED",
"kyc_identity_reason": null,
"kyc_address_reason": null,
"kyc_file_reason": null,
"first_name": "Josh",
"last_name": "Wilson",
"phone": 6157915911,
"custodian_uid": "your-external-user-id",
"cards": [{
"card": {
"id": "crd_c7015aecb8a05618",
"design_key": "blue",
"livemode": false,
"wallets": [],
"last_four": "5542",
"status": "CREATED",
"activated_at": null,
"created_at": "2016-10-19T23:20:19+00:00",
"cardholder_id": "crdhldr_1cd68f70917cb5ed"
}
}],
"created_at": "2016-10-19T23:20:17+00:00"
}
}
Retrieve a cardholder
GET /cardholders/[cardholder_id]
Arguments
Parameter | Type | Details |
---|---|---|
cardholder | required | The identifier of the customer to be retrieved. |
List all cardholders
GET /cardholders
Arguments
Parameter | Type | Details |
---|---|---|
limit | optional | A limit on the number of objects to be returned. Limit can range between 1 and 100 items. |
ending_before | optional | A cursor for use in pagination. An object ID that defines your place in the list. |
starting_after | optional | A cursor for use in pagination. An object ID that defines your place in the list. |
Example Response:
status code 200
{
"cardholders": [
{"cardholder": ... },
{"cardholder": ... }
}],
"has_more": true
}
POST /cardholders/[cardholder_id]/transactions
Arguments
Parameter | Type | Details |
---|---|---|
cardholder | required | The identifier of the cardholder. |
usd_amount | required | USD decimal representing transaction amount. |
Example Request Body:
{
"usd_amount": 200.00
}
Example Response:
status code 200
{
"transaction": {
"livemode": false,
"id": "txn_12aa2c96a548d7d2",
"authorizations": [],
"adjustments": [],
"cardholder_id": "crdhldr_1cd68f70917cb5ed",
"created_at": "2016-10-19T23:25:17+00:00",
"cardholder_email": "pat@wilson.com",
"cardholder_first_name": "Josh",
"cardholder_last_name": "Wilson",
"card_id": "crd_c7015aecb8a05618",
"description": "",
"merchant_name": null,
"merchant_locality": null,
"merchant_region": null,
"merchant_country": null,
"mcc": "7299",
"mcc_name": "Undefined",
"merchant_id": null,
"state": "pending",
"context": "PIN purchase (VISA, Signature)",
"local_amount": 200.0,
"local_currency": null,
"usd_amount": 200.0,
"cashback_amount": null
}
}
GET /cardholders/[cardholder_id]/transactions
Arguments
Parameter | Type | Details |
---|---|---|
cardholder | required | The identifier of the customer to be retrieved. |
limit | optional | A limit on the number of objects to be returned. Limit can range between 1 and 100 items. |
ending_before | optional | A cursor for use in pagination. An object ID that defines your place in the list. |
starting_after | optional | A cursor for use in pagination. An object ID that defines your place in the list. |
Example Response:
status code 200
{
"transactions": [
{"transaction": ... },
{"transaction": ... }
}],
"has_more": true
}
The ability to manage multiple spendable balances (buckets) and deposits for each cardholder.
GET /cardholders/[cardholder_id]/balances
Arguments
Parameter | Type | Details |
---|---|---|
cardholder | required | The identifier of the customer to be retrieved. |
Example Response:
status code 200
{
"balances": [{
"balance": {
"key": "default",
"cardholder_id": "crdhldr_7hw62d8",
"livemode": true,
"usd_balance": 100.00,
"usd_spendable": 25.0,
"usd_held": 75.00
}
}]
}
Ability for a custodian to set the absolute spendable dollar amount for a cardholder.
PUT /cardholders/[cardholder_id]/balances
Arguments
Parameter | Type | Details |
---|---|---|
cardholder | required | The identifier of the customer to be retrieved. |
usd_amount | required | USD amount the cardholder shall be able to spend. |
balance_key | optional | Specific balance identifier or bucket string. |
Example Request Body
{
"usd_amount": 300.00,
}
Example Response:
status code 200
{
"balance": {
"key": "default",
"cardholder_id": "crdhldr_7hw62d8",
"livemode": true,
"usd_balance": 375.00,
"usd_spendable": 300.0,
"usd_held": 75.00
}
}
POST /cardholders/[cardholder_id]/balances/deposits
Arguments
Parameter | Type | Details |
---|---|---|
cardholder | required | The identifier of the customer to be retrieved. |
usd_amount | required | USD amount the cardholder shall be able to spend. |
balance_key | optional | Specific balance identifier or bucket string. |
Example Request Body
{
"usd_amount": 50.00,
}
Example Response:
status code 200
{
"balance": {
"key": "default",
"cardholder_id": "crdhldr_7hw62d8",
"livemode": true,
"usd_balance": 425.00,
"usd_spendable": 350.0,
"usd_held": 75.00
}
}
Use the /cards
endpoint to retrieve and adjust Shift cardholder cards.
status
for a given card
object can be one of four states:
CREATED
, ACTIVATED
, DEACTIVATED
, or CLOSED
Retrieve a card
GET /cards/[card_id]
Arguments
Parameter | Type | Details |
---|---|---|
card | required | The identifier of the cardholder's card. |
Example Response:
status code 200
{
"card": {
"id": "crd_fde2d61d233455b9",
"design_key": "blue",
"livemode": true,
"wallets": [{
"wallet": {
"name": "Wilson*s iPhone",
"type": "iPhone",
"status": "ACTIVE"
}
}],
"last_four": "9497",
"status": "ACTIVATED",
"activated_at": "2016-09-27T01:46:32+00:00",
"created_at": "2016-09-27T00:54:09+00:00",
"cardholder_id": "crdhldr_2d0a6443e5da6ba7"
}
}
Status | Description |
---|---|
INACTIVE | Provisioned with wallet provider, but not yet active |
ACTIVE | Active wallet / card instance |
SUSPENDED | Temporarily unusable |
DELETED | Permanently unusable |
PUT /cards/[card_id]/pin
Arguments
Parameter | Type | Details |
---|---|---|
card | required | The identifier of the cardholder's card. |
new_pin | required | 4-digit card pin. |
PUT /cards/[card_id]/[action]
Arguments
Parameter | Type | Details |
---|---|---|
card | required | The identifier of the cardholder's card. |
action | required | One of the following strings: "ACTIVATE", "DEACTIVATE", "OPEN" or "CLOSE". |
Example Response:
status code 200
{
"card": {
"id": "crd_fde2d61d233455b9",
"design_key": "blue",
"livemode": true,
"wallets": [{
"wallet": {
"name": "Wilson*s iPhone",
"type": "iPhone",
"status": "ACTIVE"
}
}],
"last_four": "9497",
"status": "DEACTIVATED",
"activated_at": "2016-09-27T01:46:32+00:00",
"created_at": "2016-09-27T00:54:09+00:00",
"cardholder_id": "crdhldr_2d0a6443e5da6ba7"
}
}
Use the /transactions
endpoint to retrieve Shift cardholder currency movement records.
Each transaction object inlcudes state
represetning the current state of a transaction's lifecycle. state
can be one of three values: pending
, complete
or declined
.
Retrieve a transaction
GET /transactions/[transaction_id]
Arguments
Parameter | Type | Details |
---|---|---|
transaction | required | The identifier of the transaction to be retrieved. |
Example Response:
status code 200
{
"transaction": {
"livemode": true,
"id": "txn_5450e1c020e5533f",
"authorizations": [{
"authorization": {
"id": "auth_92b91bf7d31bf97b",
"authorized": true
}
}],
"adjustments": [{
"adjustment": {
"id": "adj_c96794956acc0b80",
"created_at": "2016-10-19T16:54:55+00:00",
"usd_amount": 1.26
}
}],
"cardholder_id": "crdhldr_21044d185f9edb68",
"created_at": "2016-10-19T16:54:49+00:00",
"cardholder_email": "mac@macdemarco.com",
"cardholder_first_name": "Mac",
"cardholder_last_name": "Demarco",
"card_id": "crd_a38d4d15e8978373",
"description": "STARBUCKS STORE 05757 SAN FRANCISCOCAUSA",
"merchant_name": "STARBUCKS STORE 05757",
"merchant_locality": "SAN FRANCISCO",
"merchant_region": "CA",
"merchant_country": "USA",
"mcc": "5814",
"mcc_name": "Fast Food Restaurants",
"state": "pending",
"context": "Uncategorized (VISA, Signature)",
"local_amount": 1.95,
"local_currency": "USD",
"usd_amount": 1.95,
"cashback_amount": 0.0,
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "VISA",
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null
}
}
List all transactions
GET /transactions
Arguments
Parameter | Type | Details |
---|---|---|
limit | optional | A limit on the number of objects to be returned. Limit can range between 1 and 100 items. |
ending_before | optional | A cursor for use in pagination. An object ID that defines your place in the list. |
starting_after | optional | A cursor for use in pagination. An object ID that defines your place in the list. |
Example Response:
status code 200
{
"transactions": [
{...},
{...}
],
"has_more": false
}
Example Request:
{
"authorization": {
"id": "auth_98ufn66",
"transaction_id": "txn_e17b188582494880",
"cardholder_id": "crdhldr_87fndgs5",
"card_id": "crd_iuhsf7fh",
"description": "ESSEN NEW YORK NYUSA",
"merchant_name": "ESSEN",
"merchant_locality": "NEW YORK",
"merchant_region": "NY",
"merchant_country": "USA",
"mcc": "5812",
"mcc_name": "Eating Places, Restaurants",
"state": "pending",
"local_amount": 8.79,
"local_currency": "USD",
"usd_amount": 8.79,
"cardholder_usd_balance": nil,
"authorized": nil
}
}
Example Response:
{
"authorization": {
"id": "auth_98ufn66",
"transaction_id": "txn_e17b188582494880",
"cardholder_id": "crdhldr_87fndgs5",
"card_id": "crd_iuhsf7fh",
"description": "ESSEN NEW YORK NYUSA",
"merchant_name": "ESSEN",
"merchant_locality": "NEW YORK",
"merchant_region": "NY",
"merchant_country": "USA",
"mcc": "5812",
"mcc_name": "Eating Places, Restaurants",
"state": "pending",
"local_amount": 8.79,
"local_currency": "USD",
"usd_amount": 8.79,
"cardholder_usd_balance": 7004.24,
"authorized": true
}
}
Use the /settlements
endpoint to retrieve daily settlement details.
Retrieve last settlement
GET /settlements
Example Response:
status code 200
{
"settlement": {
"livemode": true,
"id": "stlmnt_5hfi35",
"date": "2016-05-24T16:36:24+00:00",
"total_balance_due": 56943.05,
"period_balance_due": 6281.39,
"csv_url": "https://example.shiftpayments.com/settlements/stlmnt_5hfi35"
}
}
Settlement CSV
The daily settlement CSV lists every financial or reversal card network message from the previous day (PST). Note that two rows can have the same transaction_id
(e.g. capture message and reversal message).
Column | Description |
---|---|
transaction_id | Shift transaction identifier |
cardholder_id | Shift cardholder identifier |
transaction_state | Current state of the Shift transaction |
usd_amount | Current settled amount in USD |
visa_interchange | Gross Visa interchange amount |
The Shift API can push real-time data directly to your application server. Use webhooks to be notified about events that happen with your account and cardholders including transaction authorization, transaction updates and settlement information.
Creating a webhoook endpoint on your server is no different from creating any page on your website. With PHP, you might create a new .php file on your server; with a framework like Sinatra, you would add a new route with the desired URL.
To acknowledge receipt of a webhook, your endpoint should return a 2xx
HTTP status code. Any other information returned in the request headers or request body is ignored. All response codes outside this range, including 3xx
codes, will indicate to Shift that you did not receive the webhook.
If a webhook is not successfully received for any reason, Shift will continue trying to send the webhook once an hour for up to 2 days. For any webhook that failed initially, upon retry each hour, the latest state for the Shift object will be sent.
status code 200
{
"cardholder": {
"livemode": false,
"id": "crdhldr_1cd68f70917cb5ed",
"email": "pat@wilson.com",
"event": "kyc_status_update",
"kyc_passed_at": "2016-10-19T23:20:21.034+00:00",
"kyc_status": "PASSED",
"kyc_identity_reason": null,
"kyc_address_reason": null,
"kyc_file_reason": null,
"first_name": "Josh",
"last_name": "Wilson",
"phone": 6157915911,
"custodian_uid": "your-external-user-id",
"cards": [{
"card": {
"id": "crd_c7015aecb8a05618",
"design_key": "blue",
"livemode": false,
"wallets": [],
"last_four": "5542",
"status": "CREATED",
"activated_at": null,
"created_at": "2016-10-19T23:20:19+00:00",
"cardholder_id": "crdhldr_1cd68f70917cb5ed"
}
}],
"created_at": "2016-10-19T23:20:17+00:00"
}
}
{
"card": {
"id": "crd_fde2d61d233455b9",
"design_key": "blue",
"livemode": true,
"event": "pin_update",
"wallets": [{
"wallet": {
"name": "Wilson*s iPhone",
"type": "iPhone",
"status": "ACTIVE"
}
}],
"last_four": "9497",
"status": "ACTIVATED",
"activated_at": "2016-09-27T01:46:32+00:00",
"created_at": "2016-09-27T00:54:09+00:00",
"cardholder_id": "crdhldr_2d0a6443e5da6ba7"
}
}
{
"settlement": {
"livemode": true,
"id": "stlmnt_5hfi35",
"date": "2016-05-24T16:36:24+00:00",
"total_balance_due": 56943.05,
"period_balance_due": 6281.39,
"csv_url": "https://example.shiftpayments.com/settlements/stlmnt_5hfi35"
}
}
{
"transaction": {
"livemode": true,
"id": "txn_5450e1c020e5533f",
"authorizations": [{
"authorization": {
"id": "auth_92b91bf7d31bf97b",
"authorized": true
}
}],
"adjustments": [{
"adjustment": {
"id": "adj_c96794956acc0b80",
"created_at": "2016-10-19T16:54:55+00:00",
"usd_amount": 1.26
}
}],
"cardholder_id": "crdhldr_21044d185f9edb68",
"created_at": "2016-10-19T16:54:49+00:00",
"cardholder_email": "mac@macdemarco.com",
"cardholder_first_name": "Mac",
"cardholder_last_name": "Demarco",
"card_id": "crd_a38d4d15e8978373",
"description": "STARBUCKS STORE 05757 SAN FRANCISCOCAUSA",
"merchant_name": "STARBUCKS STORE 05757",
"merchant_locality": "SAN FRANCISCO",
"merchant_region": "CA",
"merchant_country": "USA",
"mcc": "5814",
"mcc_name": "Fast Food Restaurants",
"state": "pending",
"context": "Uncategorized (VISA, Signature)",
"local_amount": 1.95,
"local_currency": "USD",
"usd_amount": 1.95,
"cashback_amount": 0.0,
"card_present": false,
"ecommerce": false,
"international": false,
"emv": false,
"network": "VISA",
"dispute_at": null,
"dispute_won_at": null,
"dispute_lost_at": null
}
}
ok good