Widgets
Widgets are pre-built UI components provided by Checkbook for depositing payments, adding accounts, and displaying virtual card information. Widgets reduce development time and eliminate the need to process sensitive banking and card information.
Widgets are designed to be used with the Checkbook Marketplace, and will not work with non-marketplace users and payments.
Widgets may also return a 403 in the Network Status logs. This is fine and will not affect the widget’s ability to render.
Deposit Widget
The payment deposit widget allows users to deposit payments to their corresponding payment accounts. A separate widget exists for each of Checkbook’s payment rails:
| Deposit Method | Widget Name |
|---|---|
| ACH/RTP | checkbook.deposit.Bank |
| Push to card | checkbook.deposit.Instant |
| Mailed check | checkbook.deposit.Mail |
| PayPal | checkbook.deposit.Paypal |
| Printed check | checkbook.deposit.Print |
| Virtual card | checkbook.deposit.Vcc |
| Venmo | checkbook.deposit.Venmo |
Create recipient
import requests
owner_auth = "public_key:secret_key"
user = "mscott"
url = "https://sandbox.checkbook.io/v3/user"
payload = {
"name": "Michael Scott",
"user_id": user
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"Authorization": owner_auth
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
response_json = response.json()
user_id = response_json['id']
user_secret = response_json['secret']
user_key = response_json['key']{
"id": "9d7263e9db75473d8acf259b77c99df4",
"key": "user_key",
"secret": "user_key",
"user_id": "mscott"
}Send a payment
# Create a payment
import requests
owner_auth = "public_key:secret_key"
url = "https://sandbox.checkbook.io/v3/check/digital"
payload = {
"deposit_options": ["BANK","CARD","MAIL","PAYPAL","PRINT","VCC","VENMO"],
"amount": 5,
"name": "Michael Scott",
"recipient": user_id,
"account": account_id # id of a prefunded wallet
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"Authorization": owner_auth
}
response = requests.post(url, json=payload, headers=headers)
response_json = response.json()
check_id = response_json['id']
print(response.text){
"amount": 5.0,
"comment": null,
"date": "2025-02-26 23:13:14",
"description": null,
"id": "f2cdf7b3bde04b7a806ab8afbc984c70",
"image_uri": "https://checkbook-checks-sandbox.s3.amazonaws.com/6a0bd53c-0df5-4481-ab38-9de8bd8333ff.png",
"name": "Michael Scott",
"number": 5075,
"recipient": "mscott",
"remittance_advice": [],
"status": "UNPAID"
}Generate JWT
# Create a JWT signature
import jwt
import datetime
# Recipient's Secret Key
secret_key = user_secret
# Payload data
payload = {
"id": check_id,
"exp": datetime.datetime.utcnow() + datetime.timedelta(minutes = 30) # Expiration time
}
# Encode the JWT
encoded_jwt = jwt.encode(payload, secret_key, algorithm = "HS256",
headers={"kid": public_key}) # Recipient's publishable key
print(encoded_jwt)eyJhbGciOiJIUzI1NiIsImtpZCI6IjhmNmQzYTM1ZTVkYzRjZTM5MmFkZGVlMTRlMmFlNWI4IiwidHlwIjoiSldUIn0.
eyJpZCI6ImYyY2RmN2IzYmRlMDRiN2E4MDZhYjhhZmJjOTg0YzcwIiwiZXhwIjoxNzQwNjEzMzk5fQ.
iKVVsLWnoUOj-jeBj82yRmOZj9HyyDd_p-W3LCSMqBQRender Widget
Take the JWT, and pass it in to the appropriate deposit widget:
<html>
<head>
<script src="https://sandbox.checkbook.io/embed/checkbook-embed.js"></script>
</head>
<body>
<script type="text/javascript">
checkbook.deposit.Bank({
token: 'eyJhbGciOiJIUzI1NiIsImtpZCI6IjhmNmQzYTM1ZTVkYzRjZTM5MmFkZGVlMTRlMmFlNWI4IiwidHlwIjoiSldUIn0.eyJpZCI6ImYyY2RmN2IzYmRlMDRiN2E4MDZhYjhhZmJjOTg0YzcwIiwiZXhwIjoxNzQwNjEzMzk5fQ.iKVVsLWnoUOj-jeBj82yRmOZj9HyyDd_p-W3LCSMqBQ',
onSuccess: (response) => {
console.log(response);
},
onError: (error) => {
console.error(error);
},
}).render('#container');
</script>
<div id="container" style="width: 600px !important; height:700px !important;">
</div>
</body>
</html>Virtual Card Widget
The virtual card Widget displays the details of a virtual card including CVV, expiration date and full card number.
Create Virtual Card
# Create a virtual card
import requests
url = "https://sandbox.checkbook.io/v3/account/vcc"
payload = {
"address": {
"city": "Scranton",
"line_1": "1725 Slough Avenue",
"zip": "18501"
},
"email": "dunder-mifflin@checkbook.io"
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"Authorization": "card_owner_key:card_owner_secret_key"
}
response = requests.post(url, json=payload, headers=headers)
response_json = response.json()
vcc_id = response_json['id']
print(response.text){
"card_number": "0000", // Full Card Number can be exposed if PCI compliant
"cvv": "123",
"expiration_date": "2027-04-08",
"id": "0e62389adf3942f5b399e244dfd8988a"
}Generate JWT
import jwt
import datetime
# Payload data
payload = {
"id": vcc_id, # Virtual Card ID
"exp": datetime.datetime.utcnow() + datetime.timedelta(minutes = 30) # Optional expiration time
}
# Encode the JWT
encoded_jwt = jwt.encode(payload, "card_owner_secret_key", algorithm = "HS256",
headers={"kid": "card_owner_key"})
print(encoded_jwt)eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjdhYTczYjk4YWQ1YzQ4YjU4ODRiZWRjNWM5MTBmYmI2In0.
eyJpZCI6ImM0ZDMwZWM5ZjhjZjRhZGFhNWQ2MTNkM2JlNzIxYzc2IiwiZXhwIjoxNzQ0MDYzMTY5fQ.
R8f90nd6Uo3XUH5UzvFa_LnMCB_0M-5SM0gSkH-p4rkRender Widget
Take the JWT and cardId, and pass it in to the ViewVcc object:
<html>
<head>
<script src="https://sandbox.checkbook.io/embed/checkbook-embed.js"></script>
</head>
<body>
<script type="text/javascript">
checkbook.account.ViewVCC({
token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjdhYTczYjk4YWQ1YzQ4YjU4ODRiZWRjNWM5MTBmYmI2In0.eyJpZCI6ImM0ZDMwZWM5ZjhjZjRhZGFhNWQ2MTNkM2JlNzIxYzc2IiwiZXhwIjoxNzQ0MDYzMTY5fQ.R8f90nd6Uo3XUH5UzvFa_LnMCB_0M-5SM0gSkH-p4rk',
cardId: 'ca560f6e99594f4ea77f678eeeb9ea26',
onSuccess: (response) => {
console.log(response);
},
onError: (error) => {
console.error(error);
},
}).render('#container');
</script>
<div id="container" style="width: 600px !important; height:700px !important;">
</div>
</body>
</html>Add Account Widget
The add account Widget allows your users to add their payment accounts to your Checkbook Marketplace. A separate widget exists for each account type:
| Account Type | Widget Name |
|---|---|
| Bank | checkbook.account.AddBank |
| Debit card | checkbook.account.AddCard |
Create user
import requests
owner_auth = "public_key:secret_key"
user = "mscott"
url = "https://sandbox.checkbook.io/v3/user"
payload = {
"name": "Michael Scott",
"user_id": user
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"Authorization": owner_auth
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
response_json = response.json()
user_uuid = response_json['id']
user_secret = response_json['secret']
user_key = response_json['key']{
"id": "9d7263e9db75473d8acf259b77c99df4",
"key": "user_key",
"secret": "user_secret",
"user_id": "mscott"
}Generate JWT
# Create a JWT signature
import jwt
import datetime
# Payload data
payload = {
"id": user_uuid,
"exp": datetime.datetime.utcnow() + datetime.timedelta(minutes = 30) # Expiration time
}
# Encode the JWT
encoded_jwt = jwt.encode(payload, user_secret, algorithm = "HS256",
headers={"kid": user_key}) # User's publishable key
print(encoded_jwt)eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjQ0M2FmNjI5ZGZhODRjZGQ5OTgyN2I0NTY2NDQ2ZDk2In0.eyJpZCI6ImU4ODhmNzY2ZGFjMzRlNDA5NTBmOTJkNGEyNzk4Yzk1In0.PoUbPPihR_YyQreW5eeCzxd-Yb6C-pFp7MiwI7B84wERender Widget
Take the JWT, and pass it in to the AddBank object:
<html>
<head>
<script src="https://sandbox.checkbook.io/embed/checkbook-embed.js"></script>
</head>
<body>
<script type="text/javascript">
checkbook.account.AddBank({token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjQ0M2FmNjI5ZGZhODRjZGQ5OTgyN2I0NTY2NDQ2ZDk2In0.eyJpZCI6ImU4ODhmNzY2ZGFjMzRlNDA5NTBmOTJkNGEyNzk4Yzk1In0.PoUbPPihR_YyQreW5eeCzxd-Yb6C-pFp7MiwI7B84wE',
onSuccess: (res) => {
},
onError: (res) => {
}}).render('#container');
</script>
<div id="container" style="width: 600px !important; height:700px !important;">
</div>
</body>
</html>Widget Callbacks
In addition to server-side webhooks, Checkbook’s widgets invoke an onSuccess callback in the browser once a flow completes. The object passed to onSuccess uses camelCase field names rather than the snake_case used by the REST API.
Add Bank
The Add Bank widget calls onSuccess(bank) with a single argument describing the newly added bank account.
{
"id": "efdbaaaa17b244abba084e6c2ccfc990",
"createdTs": "Tue, 20 Oct 2026 20:10:01 -0000",
"updatedTs": "Tue, 20 Oct 2026 20:10:01 -0000",
"routingNumber": "322271627",
"accountNumber": "5678",
"name": "JPMORGAN CHASE BANK, NA",
"type": "CHECKING",
"status": "DEPOSIT_ONLY"
}| Key | Description |
|---|---|
| id | ID of the bank account |
| createdTs | Timestamp of when the account was created |
| updatedTs | Timestamp of when the account was last updated |
| routingNumber | The bank’s routing number |
| accountNumber | The last 4 digits of the account number |
| name | The bank’s name, based on routing number |
| type | Account type — for example CHECKING or SAVINGS |
| status | Status of the account — banks added through the widget start as DEPOSIT_ONLY |
accountNumber contains only the last 4 digits.
onError callbacks typically return an ordinary JavaScript Error, or a generic “Response returned an error code”. The latter is typically a result of using an invalid token.