Unofficial CLI and Python client for the Extend virtual card API
Project description
extendvcc
Unofficial CLI and Python client for the Extend virtual card API.
Disclaimer
This is an unofficial, independent client for Extend's private browser API (
api.paywithextend.com). It is not affiliated with, endorsed by, or supported by Extend, Inc. Use at your own risk. Your Extend account may be suspended for running automation against their private API.
Install
pip install extendvcc-cli
# or
pipx install extendvcc-cli
Standalone binary (no Python required): download from GitHub Releases.
Quick Start
# Log in (interactive email + password, device remembered)
extendvcc login
# List parent cards
extendvcc accounts
# List virtual cards
extendvcc cards
Enrolling a parent card is a three-step lifecycle: extendvcc enroll ... registers
the card and triggers an issuer verification email, you click the link in that email,
then extendvcc activate <id> pulls the card from PENDING to ACTIVE. Re-run activate
if it still reports PENDING.
Create a One-Time Card
extendvcc create \
--credit-card-id cc_xxx \
--name "My Card" \
--balance-cents 5000 \
--valid-to 2026-12-31
Create a Recurring Card
extendvcc create \
--credit-card-id cc_xxx \
--name "Monthly" \
--balance-cents 10000 \
--period MONTHLY \
--by-month-day 1 \
--terminator NONE
Reveal Credentials
# Show masked card number and CVC on stdout
extendvcc reveal <card-id>
# Write full credentials to a file with 0600 permissions (owner-only)
extendvcc reveal <card-id> --json-path creds.json
--json-path writes the full PAN, CVC, and expiry to a file. Without it, the card number is masked on stdout. --json is a separate global flag that controls JSON output format; it does not write a file.
Dry Run
Destructive commands accept --dry-run to preview the exact operation without
touching the network or mutating anything:
extendvcc create --credit-card-id cc_x --name "Test" --balance-cents 5000 --valid-to 2026-12-31 --dry-run
extendvcc bulk cards.csv --credit-card-id cc_x --dry-run
extendvcc cancel <card-id> --dry-run
extendvcc close <card-id> --dry-run
extendvcc update <card-id> --balance-cents 9000 --dry-run
The would-be request body (or operation descriptor) is printed as JSON to stdout;
the human-readable plan goes to stderr. So extendvcc create ... --dry-run > body.json
captures just the JSON. create/bulk resolve the recipient locally (from --recipient,
else the saved session) and never call the API; the preview is labelled approximate
when the recipient falls back to a placeholder. update --dry-run performs only the
read-only GET needed to show the accurate merged PUT body, with no mutation.
Exit Codes
The CLI uses stable exit codes so scripts and CI can branch on the outcome:
| Code | Name | Meaning |
|---|---|---|
| 0 | OK | Success. |
| 1 | ERROR | Generic failure (library error, or an aborted confirmation). |
| 2 | USAGE | Bad flags or CLI input validation (e.g. missing --valid-to). |
| 3 | AUTH_REQUIRED | Login, OTP, or a saved session is required or failed. |
| 4 | DISABLED | Kill switch tripped (account-risk); run clear-disabled --manual. |
| 5 | API_ERROR | Extend returned an error response. |
Environment Variables
| Variable | Purpose |
|---|---|
EXTENDVCC_EMAIL |
Extend account email (overrides interactive prompt) |
EXTENDVCC_PASSWORD |
Extend account password (overrides interactive prompt) |
EXTENDVCC_IMAP_USER |
IMAP email for automatic OTP retrieval |
EXTENDVCC_IMAP_PASSWORD |
IMAP app password |
EXTENDVCC_IMAP_HOST |
IMAP server (default: imap.gmail.com) |
EXTENDVCC_STATE_DIR |
Override session/state directory |
EXTENDVCC_LEDGER_PATH |
Override ledger file path |
EXTENDVCC_BRAND_ID |
Override Extend brand ID |
Python API
from extendvcc import list_cards, get_card, create_card, reveal_card
# List all virtual cards
cards = list_cards()
# Get a single card by ID
card = get_card("card_id_here")
# Reveal card credentials (PAN, CVC, expiry)
creds = reveal_card("card_id_here")
See extendvcc.__init__ for the full list of exported functions and models.
Security Notes
- The ledger never stores PAN or CVC data.
revealsaves credentials with0600file permissions.- Session tokens are stored locally with restricted permissions.
- All HTTP uses Chrome TLS fingerprinting via
impit.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file extendvcc_cli-0.1.1.tar.gz.
File metadata
- Download URL: extendvcc_cli-0.1.1.tar.gz
- Upload date:
- Size: 67.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6996513fcbae025be95813ec9015cd57af98e9a1acdc06e0be8be8adbad9130
|
|
| MD5 |
443997d03e5bd3f0d9d4fa8d20f7cb41
|
|
| BLAKE2b-256 |
c0977d935d2e7d2c05e4bbb01935d599c4cfed2cbfc40eb94803fb54be5efff1
|
Provenance
The following attestation bundles were made for extendvcc_cli-0.1.1.tar.gz:
Publisher:
release.yml on 4LAU/extendvcc
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
extendvcc_cli-0.1.1.tar.gz -
Subject digest:
d6996513fcbae025be95813ec9015cd57af98e9a1acdc06e0be8be8adbad9130 - Sigstore transparency entry: 1822356630
- Sigstore integration time:
-
Permalink:
4LAU/extendvcc@00170f693c4ef1542ba6b5999b88b91de4b64213 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/4LAU
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@00170f693c4ef1542ba6b5999b88b91de4b64213 -
Trigger Event:
push
-
Statement type:
File details
Details for the file extendvcc_cli-0.1.1-py3-none-any.whl.
File metadata
- Download URL: extendvcc_cli-0.1.1-py3-none-any.whl
- Upload date:
- Size: 46.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c2a70e615ef23fa289241492c1a465f7467341ce711d5e257eed855d3f0bb6c
|
|
| MD5 |
ceb04d652680c79bf3153b6da06a7f2e
|
|
| BLAKE2b-256 |
2bcbabcce08337467fb9c61c13981912a1fcff0f5e3e9930969f19ed602307c1
|
Provenance
The following attestation bundles were made for extendvcc_cli-0.1.1-py3-none-any.whl:
Publisher:
release.yml on 4LAU/extendvcc
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
extendvcc_cli-0.1.1-py3-none-any.whl -
Subject digest:
0c2a70e615ef23fa289241492c1a465f7467341ce711d5e257eed855d3f0bb6c - Sigstore transparency entry: 1822356672
- Sigstore integration time:
-
Permalink:
4LAU/extendvcc@00170f693c4ef1542ba6b5999b88b91de4b64213 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/4LAU
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@00170f693c4ef1542ba6b5999b88b91de4b64213 -
Trigger Event:
push
-
Statement type: